From c18dfc9c0a06f52819dee597b55b7f58e7aaf112 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Sat, 11 Jul 2026 14:16:41 -0300 Subject: [PATCH 1/4] perf(crypto): wire keccak_permute ecall into merkle/transcript/grinding Route the STARK verifier's Keccak-256 usage (Merkle tree backends, Fiat-Shamir transcript, FRI grinding) through the keccak_permute precompile on the riscv64 guest via a new PlatformKeccak256 digest wrapper, falling back to software sha3 on host. The guest previously used sha3's software permutation exclusively, making it the dominant verifier cost. Recursion guest cycles (blowup8 preset): - single query: 5,234,002,718 -> 1,722,846,582 (3.04x) - multi query: 22,494,934,472 -> 7,687,016,693 (2.93x) Also excludes the riscv-only `syscalls` crate from the root workspace: making it reachable from crypto/crypto (a workspace member) via a target-gated path dependency caused Cargo to auto-adopt it as an implicit member, so `cargo test` tried to run its bare-metal unit tests on host and aborted. Adds an end-to-end guest test (keccak_precompile) exercising the ecall-backed sponge against known Keccak-256 vectors, covering the padding edge cases (empty, rate-1, exactly-rate, multi-block input). --- Cargo.lock | 185 ++++++++-- Cargo.toml | 5 + bench_vs/lambda/recursion/Cargo.lock | 3 +- crypto/crypto/Cargo.toml | 3 + .../src/fiat_shamir/default_transcript.rs | 3 +- crypto/crypto/src/hash/mod.rs | 1 + crypto/crypto/src/hash/platform_keccak.rs | 58 +++ .../crypto/src/merkle_tree/backends/types.rs | 2 +- crypto/stark/Cargo.toml | 2 +- crypto/stark/src/grinding.rs | 3 +- .../rust/keccak_precompile/.cargo/config.toml | 5 + .../rust/keccak_precompile/Cargo.lock | 331 ++++++++++++++++++ .../rust/keccak_precompile/Cargo.toml | 9 + .../rust/keccak_precompile/src/main.rs | 26 ++ executor/tests/rust.rs | 32 ++ syscalls/src/keccak.rs | 1 + syscalls/src/random.rs | 5 +- 17 files changed, 634 insertions(+), 40 deletions(-) create mode 100644 crypto/crypto/src/hash/platform_keccak.rs create mode 100644 executor/programs/rust/keccak_precompile/.cargo/config.toml create mode 100644 executor/programs/rust/keccak_precompile/Cargo.lock create mode 100644 executor/programs/rust/keccak_precompile/Cargo.toml create mode 100644 executor/programs/rust/keccak_precompile/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index d2f699b80..c024d877c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,7 +159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -172,7 +172,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -211,7 +211,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -262,6 +262,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.22.1" @@ -392,7 +398,7 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -520,7 +526,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -568,6 +574,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + [[package]] name = "const-oid" version = "0.9.6" @@ -761,6 +773,7 @@ version = "0.1.0" dependencies = [ "bincode", "digest", + "lambda-vm-syscalls", "libc", "math", "memmap2", @@ -825,7 +838,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.111", ] [[package]] @@ -836,7 +849,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -877,7 +890,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn", + "syn 2.0.111", "unicode-xid", ] @@ -931,7 +944,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -959,6 +972,24 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "embedded-io" version = "0.4.0" @@ -988,7 +1019,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1533,7 +1564,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1639,7 +1670,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1698,6 +1729,19 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "lambda-vm-syscalls" +version = "0.1.0" +dependencies = [ + "embedded-alloc", + "getrandom 0.2.16", + "getrandom 0.3.4", + "lazy_static", + "rand 0.9.2", + "riscv", + "thiserror 1.0.69", +] + [[package]] name = "lambdaworks-crypto" version = "0.13.0" @@ -1754,6 +1798,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -1901,7 +1951,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2032,7 +2082,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2204,7 +2254,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2348,7 +2398,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2408,6 +2458,36 @@ dependencies = [ "digest", ] +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + [[package]] name = "rkyv" version = "0.8.16" @@ -2435,7 +2515,7 @@ checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2448,6 +2528,19 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -2648,7 +2741,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2670,7 +2763,7 @@ version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -2692,7 +2785,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2779,6 +2872,7 @@ dependencies = [ "bincode", "criterion 0.4.0", "crypto", + "digest", "env_logger", "itertools 0.11.0", "libc", @@ -2792,7 +2886,6 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_cbor", - "sha3", "tempfile", "test-log", "thiserror 1.0.69", @@ -2830,7 +2923,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2839,6 +2932,30 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64 0.13.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[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.111" @@ -2901,7 +3018,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2936,7 +3053,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -2947,7 +3064,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3105,7 +3222,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3182,6 +3299,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -3288,7 +3411,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -3382,7 +3505,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3393,7 +3516,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3525,7 +3648,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -3545,5 +3668,5 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] diff --git a/Cargo.toml b/Cargo.toml index 270825fe1..ec0942ce4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,11 @@ members = [ "crypto/math-cuda", "bin/cli", ] +# Riscv-only bare-metal crate, path-dependent from crypto/crypto (target-gated), +# ethrex-crypto, and guest programs. Without this exclude, Cargo auto-adopts it as +# a member (nothing else claims it), so `cargo test` runs its unit tests on host, +# which link against riscv-only symbols and abort. +exclude = ["syscalls"] resolver = "2" diff --git a/bench_vs/lambda/recursion/Cargo.lock b/bench_vs/lambda/recursion/Cargo.lock index 66048ba81..cd2f493e6 100644 --- a/bench_vs/lambda/recursion/Cargo.lock +++ b/bench_vs/lambda/recursion/Cargo.lock @@ -128,6 +128,7 @@ name = "crypto" version = "0.1.0" dependencies = [ "digest", + "lambda-vm-syscalls", "math", "rand 0.8.6", "rand_chacha 0.3.1", @@ -845,12 +846,12 @@ name = "stark" version = "0.1.0" dependencies = [ "crypto", + "digest", "itertools", "log", "math", "serde", "serde_cbor", - "sha3", "thiserror 1.0.69", ] diff --git a/crypto/crypto/Cargo.toml b/crypto/crypto/Cargo.toml index 6e3731beb..fc8754e1d 100644 --- a/crypto/crypto/Cargo.toml +++ b/crypto/crypto/Cargo.toml @@ -23,6 +23,9 @@ memmap2 = { version = "0.9", optional = true } tempfile = { version = "3", optional = true } libc = { version = "0.2", optional = true } +[target.'cfg(target_arch = "riscv64")'.dependencies] +lambda-vm-syscalls = { path = "../../syscalls" } + [dev-dependencies] math = { path = "../math", features = ["test-utils"] } rand = "0.8.5" diff --git a/crypto/crypto/src/fiat_shamir/default_transcript.rs b/crypto/crypto/src/fiat_shamir/default_transcript.rs index 7c3c0bf99..8ab3eafc3 100644 --- a/crypto/crypto/src/fiat_shamir/default_transcript.rs +++ b/crypto/crypto/src/fiat_shamir/default_transcript.rs @@ -1,6 +1,8 @@ use crate::fiat_shamir::is_transcript::{IsStarkTranscript, IsTranscript}; +use crate::hash::platform_keccak::PlatformKeccak256 as Keccak256; use core::marker::PhantomData; +use digest::Digest; use math::{ field::{ element::FieldElement, @@ -9,7 +11,6 @@ use math::{ traits::ByteConversion, }; use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng}; -use sha3::{Digest, Keccak256}; pub struct DefaultTranscript { hasher: Keccak256, diff --git a/crypto/crypto/src/hash/mod.rs b/crypto/crypto/src/hash/mod.rs index 358ee298c..78f89fca3 100644 --- a/crypto/crypto/src/hash/mod.rs +++ b/crypto/crypto/src/hash/mod.rs @@ -1,2 +1,3 @@ +pub mod platform_keccak; pub mod poseidon; pub mod sha3; diff --git a/crypto/crypto/src/hash/platform_keccak.rs b/crypto/crypto/src/hash/platform_keccak.rs new file mode 100644 index 000000000..96dfbcc6d --- /dev/null +++ b/crypto/crypto/src/hash/platform_keccak.rs @@ -0,0 +1,58 @@ +//! Keccak-256 implementation selected per target: the `keccak_permute` +//! precompile on the riscv64 guest, plain software `sha3::Keccak256` on host. +//! Wraps `lambda_vm_syscalls::keccak::Keccak256` with the `digest` crate +//! traits so it's a drop-in replacement anywhere a `D: Digest` is expected +//! (Merkle tree backends, Fiat-Shamir transcript). + +#[cfg(target_arch = "riscv64")] +mod imp { + use digest::{ + FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update, + }; + use lambda_vm_syscalls::keccak::Keccak256 as SyscallKeccak256; + + #[derive(Clone, Default)] + pub struct PlatformKeccak256(SyscallKeccak256); + + impl HashMarker for PlatformKeccak256 {} + + impl OutputSizeUser for PlatformKeccak256 { + type OutputSize = digest::typenum::U32; + } + + impl Update for PlatformKeccak256 { + fn update(&mut self, data: &[u8]) { + self.0.update(data); + } + } + + impl FixedOutput for PlatformKeccak256 { + fn finalize_into(self, out: &mut Output) { + let mut bytes = [0u8; 32]; + self.0.finalize(&mut bytes); + out.copy_from_slice(&bytes); + } + } + + impl Reset for PlatformKeccak256 { + fn reset(&mut self) { + *self = Self::default(); + } + } + + impl FixedOutputReset for PlatformKeccak256 { + fn finalize_into_reset(&mut self, out: &mut Output) { + let mut bytes = [0u8; 32]; + self.0.clone().finalize(&mut bytes); + out.copy_from_slice(&bytes); + Reset::reset(self); + } + } +} + +#[cfg(not(target_arch = "riscv64"))] +mod imp { + pub type PlatformKeccak256 = sha3::Keccak256; +} + +pub use imp::PlatformKeccak256; diff --git a/crypto/crypto/src/merkle_tree/backends/types.rs b/crypto/crypto/src/merkle_tree/backends/types.rs index 0c2a30422..2384fda3a 100644 --- a/crypto/crypto/src/merkle_tree/backends/types.rs +++ b/crypto/crypto/src/merkle_tree/backends/types.rs @@ -1,4 +1,4 @@ -use sha3::Keccak256; +use crate::hash::platform_keccak::PlatformKeccak256 as Keccak256; use super::{ field_element::FieldElementBackend, diff --git a/crypto/stark/Cargo.toml b/crypto/stark/Cargo.toml index 9e90e789e..89483bbdf 100644 --- a/crypto/stark/Cargo.toml +++ b/crypto/stark/Cargo.toml @@ -16,7 +16,7 @@ math = { path = "../math", features = [ crypto = { path = "../crypto", features = ["std", "serde"] } thiserror = "1.0.38" log = "0.4.17" -sha3 = "0.10.8" +digest = "0.10.7" serde = { version = "1.0", features = ["derive"] } itertools = "0.11.0" diff --git a/crypto/stark/src/grinding.rs b/crypto/stark/src/grinding.rs index 196b235ea..4666b7946 100644 --- a/crypto/stark/src/grinding.rs +++ b/crypto/stark/src/grinding.rs @@ -1,6 +1,7 @@ +use crypto::hash::platform_keccak::PlatformKeccak256 as Keccak256; +use digest::Digest; #[cfg(feature = "parallel")] use rayon::prelude::{IntoParallelIterator, ParallelIterator}; -use sha3::{Digest, Keccak256}; const PREFIX: [u8; 8] = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xed]; diff --git a/executor/programs/rust/keccak_precompile/.cargo/config.toml b/executor/programs/rust/keccak_precompile/.cargo/config.toml new file mode 100644 index 000000000..ca99a3f45 --- /dev/null +++ b/executor/programs/rust/keccak_precompile/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.riscv64im-lambda-vm-elf] +rustflags = [ + "--cfg", "getrandom_backend=\"custom\"", + "-C", "passes=lower-atomic" +] diff --git a/executor/programs/rust/keccak_precompile/Cargo.lock b/executor/programs/rust/keccak_precompile/Cargo.lock new file mode 100644 index 000000000..3aa2810f5 --- /dev/null +++ b/executor/programs/rust/keccak_precompile/Cargo.lock @@ -0,0 +1,331 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "keccak_precompile" +version = "0.1.0" +dependencies = [ + "lambda-vm-syscalls", +] + +[[package]] +name = "lambda-vm-syscalls" +version = "0.1.0" +dependencies = [ + "embedded-alloc", + "getrandom 0.2.17", + "getrandom 0.3.4", + "lazy_static", + "rand", + "riscv", + "thiserror", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[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.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] diff --git a/executor/programs/rust/keccak_precompile/Cargo.toml b/executor/programs/rust/keccak_precompile/Cargo.toml new file mode 100644 index 000000000..addf6e2da --- /dev/null +++ b/executor/programs/rust/keccak_precompile/Cargo.toml @@ -0,0 +1,9 @@ +[workspace] + +[package] +name = "keccak_precompile" +version = "0.1.0" +edition = "2024" + +[dependencies] +lambda-vm-syscalls = { path = "../../../../syscalls" } diff --git a/executor/programs/rust/keccak_precompile/src/main.rs b/executor/programs/rust/keccak_precompile/src/main.rs new file mode 100644 index 000000000..27d46456e --- /dev/null +++ b/executor/programs/rust/keccak_precompile/src/main.rs @@ -0,0 +1,26 @@ +use lambda_vm_syscalls::keccak::keccak256; +use lambda_vm_syscalls::syscalls; + +// Exercises the `keccak_permute`-ecall-backed sponge (`lambda_vm_syscalls::keccak`) +// against known Keccak-256 vectors: empty input, one rate block minus one byte, +// exactly one rate block, and multi-block input — the padding edge cases a +// single small input can't cover. +pub fn main() { + const RATE_BYTES: usize = 136; + + let empty = keccak256(b""); + let abc = keccak256(b"abc"); + let rate_minus_one = keccak256(&[0x5a; RATE_BYTES - 1]); + let exactly_rate = keccak256(&[0x3c; RATE_BYTES]); + let multi_block_input: Vec = (0..2 * RATE_BYTES + 17).map(|i| i as u8).collect(); + let multi_block = keccak256(&multi_block_input); + + let mut output = Vec::with_capacity(5 * 32); + output.extend_from_slice(&empty); + output.extend_from_slice(&abc); + output.extend_from_slice(&rate_minus_one); + output.extend_from_slice(&exactly_rate); + output.extend_from_slice(&multi_block); + + syscalls::commit(&output); +} diff --git a/executor/tests/rust.rs b/executor/tests/rust.rs index 458a0bd6c..ca5152de1 100644 --- a/executor/tests/rust.rs +++ b/executor/tests/rust.rs @@ -231,6 +231,38 @@ fn test_keccak() { ); } +#[test] +fn test_keccak_precompile() { + fn hex_bytes(hex: &str) -> Vec { + (0..hex.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap()) + .collect() + } + + // Known-answer vectors for the `keccak_permute`-ecall-backed sponge + // (`lambda_vm_syscalls::keccak::keccak256`), computed with the trusted + // `sha3::Keccak256` crate. Covers empty input, one rate block (136 + // bytes) minus one byte, exactly one rate block, and a multi-block + // input — the sponge's padding edge cases. + let expected: Vec = [ + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", + "03c527855334eb2e62b3b9b4d02ab76721707d3dde5fb218369640ee2edc7f3a", + "0c0a7040fb3ca12143e59ee4a8d8dceab069cc4c65e725a146563b6304ed6e72", + "e4a2f4955400b1a0dd4d52f30bdd542bda1f01f36883b8df6271da7a96cc02ef", + ] + .iter() + .flat_map(|hex| hex_bytes(hex)) + .collect(); + + run_program_and_check_public_output( + "./program_artifacts/rust/keccak_precompile.elf", + expected, + vec![], + ); +} + #[test] fn test_stdin_read_panics() { let result = run_program_without_expect("./program_artifacts/rust/stdin_read.elf", vec![]); diff --git a/syscalls/src/keccak.rs b/syscalls/src/keccak.rs index c9e2c6510..56408e339 100644 --- a/syscalls/src/keccak.rs +++ b/syscalls/src/keccak.rs @@ -25,6 +25,7 @@ const DELIMITER: u8 = 0x01; const FINAL_PAD_BIT: u8 = 0x80; /// Incremental Keccak-256 hasher. +#[derive(Clone)] pub struct Keccak256 { state: [u64; 25], buf: [u8; RATE_BYTES], diff --git a/syscalls/src/random.rs b/syscalls/src/random.rs index 18a00e866..430caf0d2 100644 --- a/syscalls/src/random.rs +++ b/syscalls/src/random.rs @@ -41,10 +41,7 @@ pub unsafe extern "C" fn sys_rand(buf: *mut u8, len: usize) { /// /// `dest_ptr` must be valid for writes of `len` bytes. #[unsafe(no_mangle)] -unsafe extern "Rust" fn __getrandom_v03_custom( - dest_ptr: *mut u8, - len: usize, -) -> Result<(), Error> { +unsafe extern "Rust" fn __getrandom_v03_custom(dest_ptr: *mut u8, len: usize) -> Result<(), Error> { print_string("getrandom called\n"); print_string("WARNING: Using getrandom is insecure\n"); From eb47e115997420d751e7062b6968b4e88bbe0cbc Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Mon, 13 Jul 2026 16:58:04 -0300 Subject: [PATCH 2/4] fix(crypto): route ELF digest through keccak_permute, cover transcript sponge pattern elf_digest still used sha3::Keccak256 directly, so the recursion guest hashed the entire inner ELF in software instead of through the keccak_permute ecall like every other hash site. Also add a KAT covering DefaultTranscript's real call pattern (small non-rate-aligned updates interleaved with finalize_reset), which the existing one-shot KAT never exercised, and drop a redundant clone+scratch-buffer in PlatformKeccak256's finalize_into/finalize_into_reset. --- crypto/crypto/src/hash/platform_keccak.rs | 9 +- .../.cargo/config.toml | 5 + .../rust/keccak_transcript_pattern/Cargo.lock | 715 ++++++++++++++++++ .../rust/keccak_transcript_pattern/Cargo.toml | 11 + .../keccak_transcript_pattern/src/main.rs | 35 + executor/tests/rust.rs | 74 +- prover/src/statement.rs | 3 +- 7 files changed, 829 insertions(+), 23 deletions(-) create mode 100644 executor/programs/rust/keccak_transcript_pattern/.cargo/config.toml create mode 100644 executor/programs/rust/keccak_transcript_pattern/Cargo.lock create mode 100644 executor/programs/rust/keccak_transcript_pattern/Cargo.toml create mode 100644 executor/programs/rust/keccak_transcript_pattern/src/main.rs diff --git a/crypto/crypto/src/hash/platform_keccak.rs b/crypto/crypto/src/hash/platform_keccak.rs index 96dfbcc6d..9325f5a4b 100644 --- a/crypto/crypto/src/hash/platform_keccak.rs +++ b/crypto/crypto/src/hash/platform_keccak.rs @@ -28,9 +28,7 @@ mod imp { impl FixedOutput for PlatformKeccak256 { fn finalize_into(self, out: &mut Output) { - let mut bytes = [0u8; 32]; - self.0.finalize(&mut bytes); - out.copy_from_slice(&bytes); + self.0.finalize((&mut out[..]).try_into().unwrap()); } } @@ -42,10 +40,7 @@ mod imp { impl FixedOutputReset for PlatformKeccak256 { fn finalize_into_reset(&mut self, out: &mut Output) { - let mut bytes = [0u8; 32]; - self.0.clone().finalize(&mut bytes); - out.copy_from_slice(&bytes); - Reset::reset(self); + core::mem::take(&mut self.0).finalize((&mut out[..]).try_into().unwrap()); } } } diff --git a/executor/programs/rust/keccak_transcript_pattern/.cargo/config.toml b/executor/programs/rust/keccak_transcript_pattern/.cargo/config.toml new file mode 100644 index 000000000..ca99a3f45 --- /dev/null +++ b/executor/programs/rust/keccak_transcript_pattern/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.riscv64im-lambda-vm-elf] +rustflags = [ + "--cfg", "getrandom_backend=\"custom\"", + "-C", "passes=lower-atomic" +] diff --git a/executor/programs/rust/keccak_transcript_pattern/Cargo.lock b/executor/programs/rust/keccak_transcript_pattern/Cargo.lock new file mode 100644 index 000000000..4e5afb1bd --- /dev/null +++ b/executor/programs/rust/keccak_transcript_pattern/Cargo.lock @@ -0,0 +1,715 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crypto" +version = "0.1.0" +dependencies = [ + "digest", + "lambda-vm-syscalls", + "math", + "rand 0.8.7", + "rand_chacha 0.3.1", + "serde", + "sha3", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak_transcript_pattern" +version = "0.1.0" +dependencies = [ + "crypto", + "digest", + "lambda-vm-syscalls", +] + +[[package]] +name = "lambda-vm-syscalls" +version = "0.1.0" +dependencies = [ + "embedded-alloc", + "getrandom 0.2.17", + "getrandom 0.3.4", + "lazy_static", + "rand 0.9.5", + "riscv", + "thiserror", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "math" +version = "0.1.0" +dependencies = [ + "getrandom 0.2.17", + "num-bigint", + "num-traits", + "rand 0.8.7", + "rayon", + "serde", + "serde_json", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[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.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.118", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/executor/programs/rust/keccak_transcript_pattern/Cargo.toml b/executor/programs/rust/keccak_transcript_pattern/Cargo.toml new file mode 100644 index 000000000..cfa257839 --- /dev/null +++ b/executor/programs/rust/keccak_transcript_pattern/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] + +[package] +name = "keccak_transcript_pattern" +version = "0.1.0" +edition = "2024" + +[dependencies] +lambda-vm-syscalls = { path = "../../../../syscalls" } +crypto = { path = "../../../../crypto/crypto" } +digest = "0.10.7" diff --git a/executor/programs/rust/keccak_transcript_pattern/src/main.rs b/executor/programs/rust/keccak_transcript_pattern/src/main.rs new file mode 100644 index 000000000..bfc56c84e --- /dev/null +++ b/executor/programs/rust/keccak_transcript_pattern/src/main.rs @@ -0,0 +1,35 @@ +use crypto::hash::platform_keccak::PlatformKeccak256; +use digest::Digest; +use lambda_vm_syscalls::syscalls; + +// Exercises `PlatformKeccak256` (the `keccak_permute`-ecall-backed sponge used +// by `DefaultTranscript`) with the same call pattern `DefaultTranscript::sample` +// drives: several small, non-rate-aligned `update()`s, then `finalize_reset()`, +// then more `update()`s seeded with the reversed prior digest. This covers the +// cross-call buffering path that a single one-shot hash can't reach. +pub fn main() { + let mut hasher = PlatformKeccak256::new(); + hasher.update(&[0xaa; 5]); + hasher.update(&[0xbb; 40]); + hasher.update(&[0xcc; 17]); + hasher.update(&[0xdd; 100]); + let digest1: [u8; 32] = hasher.finalize_reset().into(); + + let mut reversed1 = digest1; + reversed1.reverse(); + hasher.update(&reversed1); + hasher.update(&[0xee; 3]); + hasher.update(&[0xff; 130]); + let digest2: [u8; 32] = hasher.finalize_reset().into(); + + let mut reversed2 = digest2; + reversed2.reverse(); + hasher.update(&reversed2); + let digest3: [u8; 32] = hasher.finalize().into(); + + let mut output = Vec::with_capacity(3 * 32); + output.extend_from_slice(&digest1); + output.extend_from_slice(&digest2); + output.extend_from_slice(&digest3); + syscalls::commit(&output); +} diff --git a/executor/tests/rust.rs b/executor/tests/rust.rs index ca5152de1..a62c481af 100644 --- a/executor/tests/rust.rs +++ b/executor/tests/rust.rs @@ -233,27 +233,34 @@ fn test_keccak() { #[test] fn test_keccak_precompile() { - fn hex_bytes(hex: &str) -> Vec { - (0..hex.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap()) - .collect() + use tiny_keccak::Hasher; + + fn keccak256(input: &[u8]) -> [u8; 32] { + let mut output = [0u8; 32]; + let mut hasher = tiny_keccak::Keccak::v256(); + hasher.update(input); + hasher.finalize(&mut output); + output } // Known-answer vectors for the `keccak_permute`-ecall-backed sponge // (`lambda_vm_syscalls::keccak::keccak256`), computed with the trusted - // `sha3::Keccak256` crate. Covers empty input, one rate block (136 - // bytes) minus one byte, exactly one rate block, and a multi-block - // input — the sponge's padding edge cases. + // `tiny_keccak` crate. Covers empty input, one rate block (136 bytes) + // minus one byte, exactly one rate block, and a multi-block input — + // the sponge's padding edge cases. Inputs must match + // `executor/programs/rust/keccak_precompile/src/main.rs` exactly. + const RATE_BYTES: usize = 136; + let multi_block_input: Vec = (0..2 * RATE_BYTES + 17).map(|i| i as u8).collect(); + let expected: Vec = [ - "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", - "03c527855334eb2e62b3b9b4d02ab76721707d3dde5fb218369640ee2edc7f3a", - "0c0a7040fb3ca12143e59ee4a8d8dceab069cc4c65e725a146563b6304ed6e72", - "e4a2f4955400b1a0dd4d52f30bdd542bda1f01f36883b8df6271da7a96cc02ef", + keccak256(b""), + keccak256(b"abc"), + keccak256(&[0x5a; RATE_BYTES - 1]), + keccak256(&[0x3c; RATE_BYTES]), + keccak256(&multi_block_input), ] - .iter() - .flat_map(|hex| hex_bytes(hex)) + .into_iter() + .flatten() .collect(); run_program_and_check_public_output( @@ -263,6 +270,43 @@ fn test_keccak_precompile() { ); } +#[test] +fn test_keccak_transcript_pattern() { + use tiny_keccak::Hasher; + + fn keccak256(chunks: &[&[u8]]) -> [u8; 32] { + let mut output = [0u8; 32]; + let mut hasher = tiny_keccak::Keccak::v256(); + for chunk in chunks { + hasher.update(chunk); + } + hasher.finalize(&mut output); + output + } + + // Reference values for `executor/programs/rust/keccak_transcript_pattern`, + // which drives `PlatformKeccak256` the same way `DefaultTranscript::sample` + // does: several small, non-rate-aligned `update()`s per round, interleaved + // with `finalize_reset()`, each round reseeded with the reversed prior + // digest. Covers the cross-call sponge buffering that a one-shot hash of a + // whole slice can't reach. + let digest1 = keccak256(&[&[0xaa; 5], &[0xbb; 40], &[0xcc; 17], &[0xdd; 100]]); + let mut reversed1 = digest1; + reversed1.reverse(); + let digest2 = keccak256(&[&reversed1, &[0xee; 3], &[0xff; 130]]); + let mut reversed2 = digest2; + reversed2.reverse(); + let digest3 = keccak256(&[&reversed2]); + + let expected: Vec = [digest1, digest2, digest3].into_iter().flatten().collect(); + + run_program_and_check_public_output( + "./program_artifacts/rust/keccak_transcript_pattern.elf", + expected, + vec![], + ); +} + #[test] fn test_stdin_read_panics() { let result = run_program_without_expect("./program_artifacts/rust/stdin_read.elf", vec![]); diff --git a/prover/src/statement.rs b/prover/src/statement.rs index 87dab84cd..3449fa05f 100644 --- a/prover/src/statement.rs +++ b/prover/src/statement.rs @@ -10,7 +10,8 @@ //! every derived challenge differ and verification reject. use crypto::fiat_shamir::is_transcript::IsTranscript; -use sha3::{Digest, Keccak256}; +use crypto::hash::platform_keccak::PlatformKeccak256 as Keccak256; +use sha3::Digest; use crate::test_utils::E; use crate::{RuntimePageRange, TableCounts}; From 324bebadf6d34ff6e443f16345832a893b1fdcf6 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Tue, 14 Jul 2026 15:00:39 -0300 Subject: [PATCH 3/4] perf(prover): route program_id fold through platform keccak program_id_from_digest still used sha3::Keccak256 (software) instead of PlatformKeccak256, so the in-guest program-id fold bypassed the keccak_permute accelerator. statement.rs also imported the Digest trait via sha3 despite already using PlatformKeccak256, masking that the guest path never touches sha3 directly. Drop the sha3 dependency from prover in favor of digest, since PlatformKeccak256 supplies the concrete hasher on all targets. --- Cargo.lock | 2 +- bench_vs/lambda/recursion/Cargo.lock | 2 +- prover/Cargo.toml | 2 +- prover/src/recursion.rs | 3 ++- prover/src/statement.rs | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0221f27ee..ced6a78b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1713,6 +1713,7 @@ dependencies = [ "bincode", "criterion 0.5.1", "crypto", + "digest", "ecsm", "env_logger", "executor", @@ -1722,7 +1723,6 @@ dependencies = [ "postcard", "rayon", "serde", - "sha3", "stark", "sysinfo", "tikv-jemalloc-ctl", diff --git a/bench_vs/lambda/recursion/Cargo.lock b/bench_vs/lambda/recursion/Cargo.lock index ae0f23344..3af079191 100644 --- a/bench_vs/lambda/recursion/Cargo.lock +++ b/bench_vs/lambda/recursion/Cargo.lock @@ -409,13 +409,13 @@ name = "lambda-vm-prover" version = "0.1.0" dependencies = [ "crypto", + "digest", "ecsm", "executor", "log", "math", "postcard", "serde", - "sha3", "stark", "sysinfo", ] diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 4a76a41bc..186bd18ce 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -27,7 +27,7 @@ postcard = { version = "1.0", features = ["alloc"] } rayon = { version = "1.8.0", optional = true } sysinfo = { version = "0.31", default-features = false, features = ["system"] } log = "0.4" -sha3 = { version = "0.10.8", default-features = false } +digest = "0.10.7" [dev-dependencies] env_logger = "*" diff --git a/prover/src/recursion.rs b/prover/src/recursion.rs index 0c290264b..3ec22130a 100644 --- a/prover/src/recursion.rs +++ b/prover/src/recursion.rs @@ -24,8 +24,9 @@ //! [`Preset`]). A consumer must pin that outer ELF too, or a 1-query `min` //! attestation is indistinguishable from a 128-bit `blowup8` one. +use crypto::hash::platform_keccak::PlatformKeccak256 as Keccak256; +use digest::Digest; use executor::elf::Elf; -use sha3::{Digest, Keccak256}; use crate::statement::elf_digest; use crate::tables::trace_builder::Traces; diff --git a/prover/src/statement.rs b/prover/src/statement.rs index 0146fbe3e..81c18baa5 100644 --- a/prover/src/statement.rs +++ b/prover/src/statement.rs @@ -11,7 +11,7 @@ use crypto::fiat_shamir::is_transcript::IsTranscript; use crypto::hash::platform_keccak::PlatformKeccak256 as Keccak256; -use sha3::Digest; +use digest::Digest; use crate::test_utils::E; use crate::{RuntimePageRange, TableCounts}; From 934ffc1031165e05e4a37bb0353cf4ac28f50225 Mon Sep 17 00:00:00 2001 From: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:54:32 -0300 Subject: [PATCH 4/4] perf(crypto): route recursion program_id fold through keccak_permute + cleanups (#813) * perf(crypto): route recursion program_id fold through keccak_permute + cleanups Follow-ups to #802's keccak-syscall wiring. - prover/recursion.rs: program_id_from_digest ran the in-guest program_id fold on software sha3::Keccak256 -- the one verifier-guest keccak still bypassing the keccak_permute ecall. Route it through PlatformKeccak256, as statement::elf_digest already is. Correctness-neutral (software and syscall Keccak-256 are identical, so check_attestation still matches), but it removes the last software Keccak-f from the recursion guest. - Unify prover on digest::Digest (statement.rs used sha3::Digest, while grinding.rs and default_transcript.rs already use digest::Digest). No concrete sha3 type remains in prover, so swap its sha3 dependency for digest. - platform_keccak.rs: replace the two hot-path `.try_into().unwrap()`s in finalize_into / finalize_into_reset with an infallible fixed-size copy. - Cargo.toml: correct the exclude=["syscalls"] rationale -- the crate has no unit tests; host workspace builds fail because it defines a #[global_allocator] plus #[unsafe(no_mangle)] entrypoints/syscalls (and riscv asm!) that only link for riscv64im-lambda-vm-elf. * align prover digest dep with base (drop needless default-features=false) --------- Co-authored-by: Mario Rugiero --- Cargo.toml | 5 +++-- crypto/crypto/src/hash/platform_keccak.rs | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec0942ce4..8f9bbe7d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,9 @@ members = [ ] # Riscv-only bare-metal crate, path-dependent from crypto/crypto (target-gated), # ethrex-crypto, and guest programs. Without this exclude, Cargo auto-adopts it as -# a member (nothing else claims it), so `cargo test` runs its unit tests on host, -# which link against riscv-only symbols and abort. +# an implicit member (nothing else claims it), and host workspace builds then fail: +# it defines a `#[global_allocator]` plus `#[unsafe(no_mangle)]` entrypoints/syscalls +# (and riscv `asm!`) that only assemble/link for `riscv64im-lambda-vm-elf`. exclude = ["syscalls"] resolver = "2" diff --git a/crypto/crypto/src/hash/platform_keccak.rs b/crypto/crypto/src/hash/platform_keccak.rs index 9325f5a4b..199c69625 100644 --- a/crypto/crypto/src/hash/platform_keccak.rs +++ b/crypto/crypto/src/hash/platform_keccak.rs @@ -28,7 +28,9 @@ mod imp { impl FixedOutput for PlatformKeccak256 { fn finalize_into(self, out: &mut Output) { - self.0.finalize((&mut out[..]).try_into().unwrap()); + let mut digest = [0u8; 32]; + self.0.finalize(&mut digest); + out.copy_from_slice(&digest); } } @@ -40,7 +42,9 @@ mod imp { impl FixedOutputReset for PlatformKeccak256 { fn finalize_into_reset(&mut self, out: &mut Output) { - core::mem::take(&mut self.0).finalize((&mut out[..]).try_into().unwrap()); + let mut digest = [0u8; 32]; + core::mem::take(&mut self.0).finalize(&mut digest); + out.copy_from_slice(&digest); } } }