diff --git a/Cargo.lock b/Cargo.lock index 45e37c63c2..1660eea168 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2230,32 +2230,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "rustc_version 0.4.1", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "darling" version = "0.13.4" @@ -3055,12 +3029,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "fixed-hash" version = "0.8.0" @@ -6862,7 +6830,7 @@ dependencies = [ [[package]] name = "sp1-build" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anyhow", "cargo_metadata", @@ -6873,7 +6841,7 @@ dependencies = [ [[package]] name = "sp1-cli" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anstyle", "anyhow", @@ -6901,7 +6869,7 @@ dependencies = [ [[package]] name = "sp1-core-executor" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "bytemuck", @@ -6934,7 +6902,7 @@ dependencies = [ [[package]] name = "sp1-core-machine" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "cfg-if", @@ -6983,7 +6951,7 @@ dependencies = [ [[package]] name = "sp1-cuda" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "ctrlc", @@ -7000,10 +6968,9 @@ dependencies = [ [[package]] name = "sp1-curves" -version = "3.3.0" +version = "3.4.0" dependencies = [ "cfg-if", - "curve25519-dalek", "dashu", "elliptic-curve 0.13.8", "generic-array 1.1.0", @@ -7022,7 +6989,7 @@ dependencies = [ [[package]] name = "sp1-derive" -version = "3.3.0" +version = "3.4.0" dependencies = [ "quote", "syn 1.0.109", @@ -7030,7 +6997,7 @@ dependencies = [ [[package]] name = "sp1-eval" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anyhow", "bincode", @@ -7050,7 +7017,7 @@ dependencies = [ [[package]] name = "sp1-helper" -version = "3.3.0" +version = "3.4.0" dependencies = [ "sp1-build", ] @@ -7067,7 +7034,7 @@ dependencies = [ [[package]] name = "sp1-lib" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "serde", @@ -7075,7 +7042,7 @@ dependencies = [ [[package]] name = "sp1-perf" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anyhow", "bincode", @@ -7097,7 +7064,7 @@ dependencies = [ [[package]] name = "sp1-primitives" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "hex", @@ -7113,7 +7080,7 @@ dependencies = [ [[package]] name = "sp1-prover" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anyhow", "bincode", @@ -7153,7 +7120,7 @@ dependencies = [ [[package]] name = "sp1-recursion-circuit" -version = "3.3.0" +version = "3.4.0" dependencies = [ "ff 0.13.0", "hashbrown 0.14.5", @@ -7189,7 +7156,7 @@ dependencies = [ [[package]] name = "sp1-recursion-compiler" -version = "3.3.0" +version = "3.4.0" dependencies = [ "backtrace", "criterion", @@ -7214,7 +7181,7 @@ dependencies = [ [[package]] name = "sp1-recursion-core" -version = "3.3.0" +version = "3.4.0" dependencies = [ "backtrace", "ff 0.13.0", @@ -7249,7 +7216,7 @@ dependencies = [ [[package]] name = "sp1-recursion-derive" -version = "3.3.0" +version = "3.4.0" dependencies = [ "quote", "syn 1.0.109", @@ -7257,7 +7224,7 @@ dependencies = [ [[package]] name = "sp1-recursion-gnark-cli" -version = "3.3.0" +version = "3.4.0" dependencies = [ "bincode", "clap", @@ -7266,7 +7233,7 @@ dependencies = [ [[package]] name = "sp1-recursion-gnark-ffi" -version = "3.3.0" +version = "3.4.0" dependencies = [ "anyhow", "bincode", @@ -7290,7 +7257,7 @@ dependencies = [ [[package]] name = "sp1-sdk" -version = "3.3.0" +version = "3.4.0" dependencies = [ "alloy-primitives 0.8.11", "alloy-signer", @@ -7336,7 +7303,7 @@ dependencies = [ [[package]] name = "sp1-stark" -version = "3.3.0" +version = "3.4.0" dependencies = [ "arrayref", "getrandom 0.2.15", @@ -7371,7 +7338,7 @@ dependencies = [ [[package]] name = "sp1-verifier" -version = "3.3.0" +version = "3.4.0" dependencies = [ "hex", "lazy_static", @@ -7385,7 +7352,7 @@ dependencies = [ [[package]] name = "sp1-zkvm" -version = "3.3.0" +version = "3.4.0" dependencies = [ "cfg-if", "getrandom 0.2.15", @@ -7395,7 +7362,7 @@ dependencies = [ "p3-field", "rand 0.8.5", "sha2 0.10.8", - "sp1-lib 3.3.0", + "sp1-lib 3.4.0", "sp1-primitives", ] diff --git a/Cargo.toml b/Cargo.toml index 0633339d9c..9d2991044d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "3.3.0" +version = "3.4.0" edition = "2021" license = "MIT OR Apache-2.0" repository = "https://github.com/succinctlabs/sp1" @@ -47,26 +47,26 @@ debug-assertions = true [workspace.dependencies] # sp1 -sp1-build = { path = "crates/build", version = "3.3.0" } -sp1-cli = { path = "crates/cli", version = "3.3.0", default-features = false } -sp1-core-machine = { path = "crates/core/machine", version = "3.3.0" } -sp1-core-executor = { path = "crates/core/executor", version = "3.3.0" } -sp1-curves = { path = "crates/curves", version = "3.3.0" } -sp1-derive = { path = "crates/derive", version = "3.3.0" } -sp1-eval = { path = "crates/eval", version = "3.3.0" } -sp1-helper = { path = "crates/helper", version = "3.3.0", default-features = false } -sp1-primitives = { path = "crates/primitives", version = "3.3.0" } -sp1-prover = { path = "crates/prover", version = "3.3.0" } -sp1-recursion-compiler = { path = "crates/recursion/compiler", version = "3.3.0" } -sp1-recursion-core = { path = "crates/recursion/core", version = "3.3.0", default-features = false } -sp1-recursion-derive = { path = "crates/recursion/derive", version = "3.3.0", default-features = false } -sp1-recursion-gnark-ffi = { path = "crates/recursion/gnark-ffi", version = "3.3.0", default-features = false } -sp1-recursion-circuit = { path = "crates/recursion/circuit", version = "3.3.0", default-features = false } -sp1-sdk = { path = "crates/sdk", version = "3.3.0" } -sp1-cuda = { path = "crates/cuda", version = "3.3.0" } -sp1-stark = { path = "crates/stark", version = "3.3.0" } -sp1-lib = { path = "crates/zkvm/lib", version = "3.3.0", default-features = false } -sp1-zkvm = { path = "crates/zkvm/entrypoint", version = "3.3.0", default-features = false } +sp1-build = { path = "crates/build", version = "3.4.0" } +sp1-cli = { path = "crates/cli", version = "3.4.0", default-features = false } +sp1-core-machine = { path = "crates/core/machine", version = "3.4.0" } +sp1-core-executor = { path = "crates/core/executor", version = "3.4.0" } +sp1-curves = { path = "crates/curves", version = "3.4.0" } +sp1-derive = { path = "crates/derive", version = "3.4.0" } +sp1-eval = { path = "crates/eval", version = "3.4.0" } +sp1-helper = { path = "crates/helper", version = "3.4.0", default-features = false } +sp1-primitives = { path = "crates/primitives", version = "3.4.0" } +sp1-prover = { path = "crates/prover", version = "3.4.0" } +sp1-recursion-compiler = { path = "crates/recursion/compiler", version = "3.4.0" } +sp1-recursion-core = { path = "crates/recursion/core", version = "3.4.0", default-features = false } +sp1-recursion-derive = { path = "crates/recursion/derive", version = "3.4.0", default-features = false } +sp1-recursion-gnark-ffi = { path = "crates/recursion/gnark-ffi", version = "3.4.0", default-features = false } +sp1-recursion-circuit = { path = "crates/recursion/circuit", version = "3.4.0", default-features = false } +sp1-sdk = { path = "crates/sdk", version = "3.4.0" } +sp1-cuda = { path = "crates/cuda", version = "3.4.0" } +sp1-stark = { path = "crates/stark", version = "3.4.0" } +sp1-lib = { path = "crates/zkvm/lib", version = "3.4.0", default-features = false } +sp1-zkvm = { path = "crates/zkvm/entrypoint", version = "3.4.0", default-features = false } # p3 p3-air = "0.1.4-succinct" diff --git a/book/writing-programs/patched-crates.md b/book/writing-programs/patched-crates.md index c3a7358f82..bb64c78df6 100644 --- a/book/writing-programs/patched-crates.md +++ b/book/writing-programs/patched-crates.md @@ -36,6 +36,9 @@ sha3-v0-10-6 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", packa sha3-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha3", tag = "sha3-v0.10.8-patch-v1" } crypto-bigint = { git = "https://github.com/sp1-patches/RustCrypto-bigint", tag = "crypto_bigint-v0.5.5-patch-v1" } tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", tag = "tiny_keccak-v2.0.2-patch-v1" } +# For sp1 versions >= 3.4.0 +curve25519-dalek = { git = "https://github.com/sp1-patches/curve25519-dalek", tag = "patch-v4.1.3-v3.4.0" } +# For sp1 versions < 3.4.0 curve25519-dalek = { git = "https://github.com/sp1-patches/curve25519-dalek", tag = "curve25519_dalek-v4.1.3-patch-v1" } curve25519-dalek-ng = { git = "https://github.com/sp1-patches/curve25519-dalek-ng", tag = "curve25519_dalek_ng-v4.1.1-patch-v1" } ed25519-consensus = { git = "https://github.com/sp1-patches/ed25519-consensus", tag = "ed25519_consensus-v2.1.0-patch-v1" } diff --git a/crates/core/executor/src/hook.rs b/crates/core/executor/src/hook.rs index cbdb0db3db..09a40cd19a 100644 --- a/crates/core/executor/src/hook.rs +++ b/crates/core/executor/src/hook.rs @@ -18,6 +18,9 @@ pub const FD_ECRECOVER_HOOK: u32 = 5; /// The file descriptor through which to access `hook_ecrecover_2`. pub const FD_ECRECOVER_HOOK_2: u32 = 7; +/// The file descriptor through which to access `hook_ed_decompress`. +pub const FD_EDDECOMPRESS: u32 = 8; + /// A runtime hook. May be called during execution by writing to a specified file descriptor, /// accepting and returning arbitrary data. pub trait Hook { @@ -82,6 +85,7 @@ impl<'a> Default for HookRegistry<'a> { // add an assertion to the test `hook_fds_match` below. (FD_ECRECOVER_HOOK, hookify(hook_ecrecover)), (FD_ECRECOVER_HOOK_2, hookify(hook_ecrecover_v2)), + (FD_EDDECOMPRESS, hookify(hook_ed_decompress)), ]); Self { table } @@ -179,8 +183,9 @@ pub fn hook_ecrecover_v2(_: HookEnv, buf: &[u8]) -> Vec> { sig = sig_normalized; recovery_id ^= 1; }; - let recid = RecoveryId::from_byte(recovery_id).expect("Computed recovery ID is invalid, this is a bug."); - + let recid = RecoveryId::from_byte(recovery_id) + .expect("Computed recovery ID is invalid, this is a bug."); + // Attempting to recvover the public key has failed, write a 0 to indicate to the caller. let Ok(recovered_key) = VerifyingKey::recover_from_prehash(&msg_hash[..], &sig, recid) else { return vec![vec![0]]; @@ -194,6 +199,31 @@ pub fn hook_ecrecover_v2(_: HookEnv, buf: &[u8]) -> Vec> { vec![vec![1], bytes.to_vec(), s_inverse.to_bytes().to_vec()] } +/// Checks if a compressed Edwards point can be decompressed. +/// +/// # Arguments +/// * `env` - The environment in which the hook is invoked. +/// * `buf` - The buffer containing the compressed Edwards point. +/// - The compressed Edwards point is 32 bytes. +/// - The high bit of the last byte is the sign bit. +/// +/// The result is either `0` if the point cannot be decompressed, or `1` if it can. +/// +/// WARNING: This function merely hints at the validity of the compressed point. These values must +/// be constrained by the zkVM for correctness. +#[must_use] +pub fn hook_ed_decompress(_: HookEnv, buf: &[u8]) -> Vec> { + let Ok(point) = sp1_curves::curve25519_dalek::CompressedEdwardsY::from_slice(buf) else { + return vec![vec![0]]; + }; + + if sp1_curves::edwards::ed25519::decompress(&point).is_some() { + vec![vec![1]] + } else { + vec![vec![0]] + } +} + #[cfg(test)] pub mod tests { use super::*; diff --git a/crates/core/executor/src/syscalls/precompiles/edwards/decompress.rs b/crates/core/executor/src/syscalls/precompiles/edwards/decompress.rs index 287101fbfd..e448c09ba6 100644 --- a/crates/core/executor/src/syscalls/precompiles/edwards/decompress.rs +++ b/crates/core/executor/src/syscalls/precompiles/edwards/decompress.rs @@ -53,7 +53,8 @@ impl Syscall for EdwardsDecompressSyscall { // Compute actual decompressed X let compressed_y = CompressedEdwardsY(compressed_edwards_y); - let decompressed = decompress(&compressed_y); + let decompressed = + decompress(&compressed_y).expect("Decompression failed, syscall invariant violated."); let mut decompressed_x_bytes = decompressed.x.to_bytes_le(); decompressed_x_bytes.resize(32, 0u8); diff --git a/crates/core/machine/src/operations/field/field_sqrt.rs b/crates/core/machine/src/operations/field/field_sqrt.rs index a0f40c6a48..dbe4e4806a 100644 --- a/crates/core/machine/src/operations/field/field_sqrt.rs +++ b/crates/core/machine/src/operations/field/field_sqrt.rs @@ -224,7 +224,11 @@ mod tests { let mut row = [F::zero(); NUM_TEST_COLS]; let cols: &mut TestCols = row.as_mut_slice().borrow_mut(); cols.a = P::to_limbs_field::(a); - cols.sqrt.populate(&mut blu_events, 1, a, ed25519_sqrt); + cols.sqrt.populate(&mut blu_events, 1, a, |p| { + ed25519_sqrt(p).expect( + "By now we should have validated the sqrt exists, this is a bug", + ) + }); output.add_byte_lookup_events(blu_events); row }) diff --git a/crates/core/machine/src/syscall/precompiles/edwards/ed_decompress.rs b/crates/core/machine/src/syscall/precompiles/edwards/ed_decompress.rs index c9c5ae93c8..90c6768f14 100644 --- a/crates/core/machine/src/syscall/precompiles/edwards/ed_decompress.rs +++ b/crates/core/machine/src/syscall/precompiles/edwards/ed_decompress.rs @@ -99,7 +99,9 @@ impl EdDecompressCols { let dyy = self.dyy.populate(blu_events, shard, &E::d_biguint(), &yy, FieldOperation::Mul); let v = self.v.populate(blu_events, shard, &one, &dyy, FieldOperation::Add); let u_div_v = self.u_div_v.populate(blu_events, shard, &u, &v, FieldOperation::Div); - let x = self.x.populate(blu_events, shard, &u_div_v, ed25519_sqrt); + let x = self.x.populate(blu_events, shard, &u_div_v, |p| { + ed25519_sqrt(p).expect("ed25519_sqrt failed, syscall invariant violated") + }); self.neg_x.populate(blu_events, shard, &BigUint::zero(), &x, FieldOperation::Sub); } } diff --git a/crates/curves/Cargo.toml b/crates/curves/Cargo.toml index 8d7f16afcc..ec09d2d1d7 100644 --- a/crates/curves/Cargo.toml +++ b/crates/curves/Cargo.toml @@ -13,7 +13,6 @@ categories = { workspace = true } num = "0.4.3" serde = { version = "1.0.207", features = ["derive"] } typenum = "1.17.0" -curve25519-dalek = { version = "4.1.2" } k256 = { version = "0.13.3", features = ["expose-field"] } generic-array = { version = "1.1.0", features = ["alloc", "serde"] } amcl = { package = "snowbridge-amcl", version = "1.0.2", default-features = false, features = [ diff --git a/crates/curves/src/edwards/ed25519.rs b/crates/curves/src/edwards/ed25519.rs index c2a823c603..4d1be91ac0 100644 --- a/crates/curves/src/edwards/ed25519.rs +++ b/crates/curves/src/edwards/ed25519.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use curve25519_dalek::edwards::CompressedEdwardsY; +use crate::curve25519_dalek::CompressedEdwardsY; use generic_array::GenericArray; use num::{BigUint, Num, One}; use serde::{Deserialize, Serialize}; @@ -72,7 +72,7 @@ impl EdwardsParameters for Ed25519Parameters { /// /// This function always returns the nonnegative square root, in the sense that the least /// significant bit of the result is always 0. -pub fn ed25519_sqrt(a: &BigUint) -> BigUint { +pub fn ed25519_sqrt(a: &BigUint) -> Option { // Here is a description of how to calculate sqrt in the Curve25519 base field: // ssh://git@github.com/succinctlabs/curve25519-dalek/blob/ // e2d1bd10d6d772af07cac5c8161cd7655016af6d/curve25519-dalek/src/field.rs#L256 @@ -108,7 +108,7 @@ pub fn ed25519_sqrt(a: &BigUint) -> BigUint { let flipped_sign_sqrt = beta_squared == neg_a; if !correct_sign_sqrt && !flipped_sign_sqrt { - panic!("a is not a square"); + return None; } let beta_bytes = beta.to_bytes_le(); @@ -116,10 +116,10 @@ pub fn ed25519_sqrt(a: &BigUint) -> BigUint { beta = (&modulus - &beta) % &modulus; } - beta + Some(beta) } -pub fn decompress(compressed_point: &CompressedEdwardsY) -> AffinePoint { +pub fn decompress(compressed_point: &CompressedEdwardsY) -> Option> { let mut point_bytes = *compressed_point.as_bytes(); let sign = point_bytes[31] >> 7 == 1; // mask out the sign bit @@ -134,7 +134,7 @@ pub fn decompress(compressed_point: &CompressedEdwardsY) -> AffinePoint let v_inv = v.modpow(&(modulus - BigUint::from(2u64)), modulus); let u_div_v = (u * &v_inv) % modulus; - let mut x = ed25519_sqrt(&u_div_v); + let mut x = ed25519_sqrt(&u_div_v)?; // sqrt always returns the nonnegative square root, // so we negate according to the supplied sign bit. @@ -142,7 +142,7 @@ pub fn decompress(compressed_point: &CompressedEdwardsY) -> AffinePoint x = modulus - &x; } - AffinePoint::new(x, y.clone()) + Some(AffinePoint::new(x, y.clone())) } #[cfg(test)] @@ -178,7 +178,7 @@ mod tests { CompressedEdwardsY(compressed) }; - assert_eq!(point, decompress(&compressed_point)); + assert_eq!(point, decompress(&compressed_point).unwrap()); // Double the point to create a "random" point for the next iteration. point = point.clone() + point.clone(); diff --git a/crates/curves/src/lib.rs b/crates/curves/src/lib.rs index 7b91ab429f..b97bbc61d1 100644 --- a/crates/curves/src/lib.rs +++ b/crates/curves/src/lib.rs @@ -7,7 +7,39 @@ pub mod utils; pub mod weierstrass; pub mod curve25519_dalek { - pub use curve25519_dalek::edwards::CompressedEdwardsY; + /// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is + /// determined by the \\(y\\)-coordinate and the sign of \\(x\\). + /// + /// The first 255 bits of a `CompressedEdwardsY` represent the + /// \\(y\\)-coordinate. The high bit of the 32nd byte gives the sign of \\(x\\). + /// + /// Note: This is taken from the `curve25519-dalek` crate. + #[derive(Copy, Clone, Eq, PartialEq, Hash)] + pub struct CompressedEdwardsY(pub [u8; 32]); + + impl CompressedEdwardsY { + /// View this `CompressedEdwardsY` as a byte array. + pub fn as_bytes(&self) -> &[u8; 32] { + &self.0 + } + + /// Consume this `CompressedEdwardsY` and return the underlying byte array. + pub fn to_bytes(&self) -> [u8; 32] { + self.0 + } + + /// Construct a `CompressedEdwardsY` from a slice of bytes. + /// + /// # Errors + /// + /// Returns [`TryFromSliceError`] if the input `bytes` slice does not have + /// a length of 32. + pub fn from_slice( + bytes: &[u8], + ) -> Result { + bytes.try_into().map(CompressedEdwardsY) + } + } } pub mod k256 { diff --git a/crates/zkvm/lib/src/io.rs b/crates/zkvm/lib/src/io.rs index b44d1edae0..921669423a 100644 --- a/crates/zkvm/lib/src/io.rs +++ b/crates/zkvm/lib/src/io.rs @@ -18,6 +18,9 @@ pub const FD_ECRECOVER_HOOK: u32 = 5; /// The file descriptor through which to access `hook_ecrecover_2`. pub const FD_ECRECOVER_HOOK_2: u32 = 7; +/// The file descriptor through which to access `hook_ed_decompress`. +pub const FD_EDDECOMPRESS: u32 = 8; + /// A writer that writes to a file descriptor inside the zkVM. struct SyscallWriter { fd: u32, diff --git a/examples/elf/riscv32im-succinct-zkvm-elf b/examples/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000000..fc03bd2725 Binary files /dev/null and b/examples/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/patch-testing/program/src/main.rs b/examples/patch-testing/program/src/main.rs index cfa7829209..4089fdff19 100644 --- a/examples/patch-testing/program/src/main.rs +++ b/examples/patch-testing/program/src/main.rs @@ -81,15 +81,31 @@ fn test_curve25519_dalek_ng() { /// Emits ED_DECOMPRESS syscall. fn test_curve25519_dalek() { - let input = [1u8; 32]; - let y = CompressedEdwardsY_dalek(input); + let input_passing = [1u8; 32]; + + // This y-coordinate is not square, and therefore not on the curve + let limbs: [u64; 4] = + [8083970408152925034, 11907700107021980321, 16259949789167878387, 5645861033211660086]; + + // convert to bytes + let input_failing: [u8; 32] = + limbs.iter().flat_map(|l| l.to_be_bytes()).collect::>().try_into().unwrap(); + + let y_passing = CompressedEdwardsY_dalek(input_passing); println!("cycle-tracker-start: curve25519-dalek decompress"); - let decompressed_key = y.decompress().unwrap(); + let decompressed_key = y_passing.decompress().unwrap(); println!("cycle-tracker-end: curve25519-dalek decompress"); let compressed_key = decompressed_key.compress(); - assert_eq!(compressed_key, y); + assert_eq!(compressed_key, y_passing); + + let y_failing = CompressedEdwardsY_dalek(input_failing); + println!("cycle-tracker-start: curve25519-dalek decompress"); + let decompressed_key = y_failing.decompress(); + println!("cycle-tracker-end: curve25519-dalek decompress"); + + assert!(decompressed_key.is_none()); } /// Emits KECCAK_PERMUTE syscalls.