diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index 779af8f2568110..e70c10d070b7e9 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -27,3 +27,6 @@ fi # anza migration stopgap. can be removed when agave is fully recommended for public usage. sed -i 's/solana-geyser-plugin-interface/agave-geyser-plugin-interface/g' ./Cargo.toml + +# should be removed when spl bump their curve25519-dalek +sed -i "s/^curve25519-dalek =.*/curve25519-dalek = \"4.1.3\"/" token/confidential-transfer/proof-generation/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 9e0057d5fb7986..ce621c8bd03b18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -931,7 +931,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.5", + "block-padding", "byte-tools", "byteorder", "generic-array 0.12.4", @@ -943,7 +943,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", "generic-array 0.14.7", ] @@ -965,12 +964,6 @@ dependencies = [ "byte-tools", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "borsh" version = "0.10.3" @@ -1732,16 +1725,45 @@ dependencies = [ [[package]] name = "curve25519-dalek" version = "3.2.1" -source = "git+https://github.com/anza-xyz/curve25519-dalek.git?rev=b500cdc2a920cd5bff9e2dd974d7b97349d61464#b500cdc2a920cd5bff9e2dd974d7b97349d61464" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rand_core 0.6.4", + "rustc_version 0.4.1", "serde", "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.76", +] + [[package]] name = "darling" version = "0.20.1" @@ -1996,7 +2018,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.1", "ed25519", "rand 0.7.3", "serde", @@ -2171,6 +2193,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "filedescriptor" version = "0.8.1" @@ -5231,18 +5259,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug 0.3.0", -] - [[package]] name = "sha3" version = "0.10.8" @@ -6176,7 +6192,7 @@ version = "2.0.9" dependencies = [ "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-program", "thiserror", ] @@ -6717,7 +6733,7 @@ dependencies = [ "bincode", "bv", "caps", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "dlopen2", "fnv", "lazy_static", @@ -6810,7 +6826,7 @@ dependencies = [ "bytemuck_derive", "console_error_panic_hook", "console_log", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "getrandom 0.2.10", "itertools 0.12.1", "js-sys", @@ -6831,7 +6847,14 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.10.8", +<<<<<<< HEAD "sha3 0.10.8", +======= + "sha3", + "solana-atomic-u64", + "solana-decode-error", + "solana-define-syscall", +>>>>>>> 6e23e69f09 (chore: bump curve25519-dalek from 3.2.1 to 4.1.3 (#2252)) "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", @@ -7257,7 +7280,7 @@ dependencies = [ "bytemuck_derive", "byteorder", "chrono", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "derivation-path", "digest 0.10.7", "ed25519-dalek", @@ -7286,7 +7309,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "siphasher", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -7924,17 +7947,17 @@ dependencies = [ "bincode", "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "itertools 0.12.1", "lazy_static", "merlin", "num-derive", "num-traits", - "rand 0.7.3", + "rand 0.8.5", "serde", "serde_derive", "serde_json", - "sha3 0.9.1", + "sha3", "solana-program", "solana-sdk", "subtle", @@ -7949,7 +7972,7 @@ version = "2.0.9" dependencies = [ "bytemuck", "criterion", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "num-derive", "num-traits", "solana-program-runtime", @@ -7962,7 +7985,7 @@ name = "solana-zk-token-proof-program-tests" version = "2.0.9" dependencies = [ "bytemuck", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-compute-budget", "solana-program-test", "solana-sdk", @@ -7979,17 +8002,17 @@ dependencies = [ "bytemuck", "bytemuck_derive", "byteorder", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "itertools 0.12.1", "lazy_static", "merlin", "num-derive", "num-traits", - "rand 0.7.3", + "rand 0.8.5", "serde", "serde_derive", "serde_json", - "sha3 0.9.1", + "sha3", "solana-curve25519", "solana-program", "solana-sdk", diff --git a/Cargo.toml b/Cargo.toml index 2b5cce2c163f93..5413fd9b16f01b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -193,8 +193,13 @@ criterion = "0.5.1" criterion-stats = "0.3.0" crossbeam-channel = "0.5.13" csv = "1.3.0" +<<<<<<< HEAD ctrlc = "3.4.4" curve25519-dalek = "3.2.1" +======= +ctrlc = "3.4.5" +curve25519-dalek = { version = "4.1.3", features = ["digest", "rand_core"] } +>>>>>>> 6e23e69f09 (chore: bump curve25519-dalek from 3.2.1 to 4.1.3 (#2252)) dashmap = "5.5.3" derivation-path = { version = "0.2.0", default-features = false } derivative = "2.2.0" @@ -499,38 +504,16 @@ solana-program = { path = "sdk/program" } solana-zk-sdk = { path = "zk-sdk" } solana-zk-token-sdk = { path = "zk-token-sdk" } -# Our dependency tree has `curve25519-dalek` v3.2.1. They have removed the -# constraint in the next major release. The commit that removes the `zeroize` -# constraint was added to multiple release branches, but not to the 3.2 branch. -# -# `curve25519-dalek` maintainers are saying they do not want to invest any more -# time in the 3.2 release: -# -# https://github.com/dalek-cryptography/curve25519-dalek/issues/452#issuecomment-1749809428 -# -# So we have to fork and create our own release, based on v3.2.1, with the -# commit that removed `zeroize` constraint on the `main` branch cherry-picked on -# top. -# -# `curve25519-dalek` v3.2.1 release: -# -# https://github.com/dalek-cryptography/curve25519-dalek/releases/tag/3.2.1 -# -# Corresponds to commit -# -# https://github.com/dalek-cryptography/curve25519-dalek/commit/29e5c29b0e5c6821e4586af58b0d0891dd2ec639 -# -# Comparison with `b500cdc2a920cd5bff9e2dd974d7b97349d61464`: -# -# https://github.com/dalek-cryptography/curve25519-dalek/compare/3.2.1...solana-labs:curve25519-dalek:b500cdc2a920cd5bff9e2dd974d7b97349d61464 -# -# Or, using the branch name instead of the hash: -# -# https://github.com/dalek-cryptography/curve25519-dalek/compare/3.2.1...solana-labs:curve25519-dalek:3.2.1-unpin-zeroize -# -[patch.crates-io.curve25519-dalek] -git = "https://github.com/anza-xyz/curve25519-dalek.git" -rev = "b500cdc2a920cd5bff9e2dd974d7b97349d61464" +# curve25519-dalek uses the simd backend by default in v4 if possible, +# which has very slow performance on some platforms with opt-level 0, +# which is the default for dev and test builds. +# This slowdown causes certain interactions in the solana-test-validator, +# such as verifying ZK proofs in transactions, to take much more than 400ms, +# creating problems in the testing environment. +# To enable better performance in solana-test-validator during tests and dev builds, +# we override the opt-level to 3 for the crate. +[profile.dev.package.curve25519-dalek] +opt-level = 3 # Solana RPC nodes experience stalls when running with `tokio` containing this # commit: diff --git a/curves/curve25519/src/edwards.rs b/curves/curve25519/src/edwards.rs index 4de6bf81456601..4b4893da6410d2 100644 --- a/curves/curve25519/src/edwards.rs +++ b/curves/curve25519/src/edwards.rs @@ -63,7 +63,10 @@ mod target_arch { type Error = Curve25519Error; fn try_from(pod: &PodEdwardsPoint) -> Result { - CompressedEdwardsY::from_slice(&pod.0) + let Ok(compressed_edwards_y) = CompressedEdwardsY::from_slice(&pod.0) else { + return Err(Curve25519Error::PodConversion); + }; + compressed_edwards_y .decompress() .ok_or(Curve25519Error::PodConversion) } @@ -73,9 +76,10 @@ mod target_arch { type Point = Self; fn validate_point(&self) -> bool { - CompressedEdwardsY::from_slice(&self.0) - .decompress() - .is_some() + let Ok(compressed_edwards_y) = CompressedEdwardsY::from_slice(&self.0) else { + return false; + }; + compressed_edwards_y.decompress().is_some() } } diff --git a/curves/curve25519/src/ristretto.rs b/curves/curve25519/src/ristretto.rs index e0b47c15f1dfbe..1c71bfeed95fd3 100644 --- a/curves/curve25519/src/ristretto.rs +++ b/curves/curve25519/src/ristretto.rs @@ -63,7 +63,10 @@ mod target_arch { type Error = Curve25519Error; fn try_from(pod: &PodRistrettoPoint) -> Result { - CompressedRistretto::from_slice(&pod.0) + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(&pod.0) else { + return Err(Curve25519Error::PodConversion); + }; + compressed_ristretto .decompress() .ok_or(Curve25519Error::PodConversion) } @@ -73,9 +76,10 @@ mod target_arch { type Point = Self; fn validate_point(&self) -> bool { - CompressedRistretto::from_slice(&self.0) - .decompress() - .is_some() + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(&self.0) else { + return false; + }; + compressed_ristretto.decompress().is_some() } } diff --git a/curves/curve25519/src/scalar.rs b/curves/curve25519/src/scalar.rs index f840a27c1b4980..5df77de1aa1e01 100644 --- a/curves/curve25519/src/scalar.rs +++ b/curves/curve25519/src/scalar.rs @@ -18,7 +18,9 @@ mod target_arch { type Error = Curve25519Error; fn try_from(pod: &PodScalar) -> Result { - Scalar::from_canonical_bytes(pod.0).ok_or(Curve25519Error::PodConversion) + Scalar::from_canonical_bytes(pod.0) + .into_option() + .ok_or(Curve25519Error::PodConversion) } } @@ -32,7 +34,9 @@ mod target_arch { type Error = Curve25519Error; fn try_from(pod: PodScalar) -> Result { - Scalar::from_canonical_bytes(pod.0).ok_or(Curve25519Error::PodConversion) + Scalar::from_canonical_bytes(pod.0) + .into_option() + .ok_or(Curve25519Error::PodConversion) } } } diff --git a/perf/src/sigverify.rs b/perf/src/sigverify.rs index 6078961d42db71..12a8d92f54137b 100644 --- a/perf/src/sigverify.rs +++ b/perf/src/sigverify.rs @@ -1280,7 +1280,7 @@ mod tests { for _ in 0..1_000_000 { thread_rng().fill(&mut input); let ans = get_checked_scalar(&input); - let ref_ans = Scalar::from_canonical_bytes(input); + let ref_ans = Scalar::from_canonical_bytes(input).into_option(); if let Some(ref_ans) = ref_ans { passed += 1; assert_eq!(ans.unwrap(), ref_ans.to_bytes()); @@ -1315,7 +1315,7 @@ mod tests { for _ in 0..1_000_000 { thread_rng().fill(&mut input); let ans = check_packed_ge_small_order(&input); - let ref_ge = CompressedEdwardsY::from_slice(&input); + let ref_ge = CompressedEdwardsY::from_slice(&input).unwrap(); if let Some(ref_element) = ref_ge.decompress() { if ref_element.is_small_order() { assert!(!ans); diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index dd67adf40de351..ab106d4350dd1b 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -701,7 +701,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", "generic-array", ] @@ -714,12 +713,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "borsh" version = "0.10.3" @@ -1242,11 +1235,39 @@ dependencies = [ "byteorder 1.5.0", "digest 0.9.0", "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rand_core 0.6.4", + "rustc_version", "serde", "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.58", +] + [[package]] name = "darling" version = "0.20.1" @@ -1484,7 +1505,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 3.2.1", "ed25519", "rand 0.7.3", "serde", @@ -1662,6 +1683,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "filetime" version = "0.2.10" @@ -4365,18 +4392,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - [[package]] name = "sha3" version = "0.10.8" @@ -4930,7 +4945,7 @@ version = "2.0.9" dependencies = [ "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-program", "thiserror", ] @@ -5233,7 +5248,7 @@ dependencies = [ "bincode", "bv", "caps", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "dlopen2", "fnv", "lazy_static", @@ -5295,7 +5310,7 @@ dependencies = [ "bytemuck_derive", "console_error_panic_hook", "console_log", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "getrandom 0.2.10", "js-sys", "lazy_static", @@ -5313,7 +5328,17 @@ dependencies = [ "serde_bytes", "serde_derive", "sha2 0.10.8", +<<<<<<< HEAD "sha3 0.10.8", +======= + "sha3", + "solana-atomic-u64", + "solana-decode-error", + "solana-define-syscall", + "solana-msg", + "solana-program-memory", + "solana-sanitize", +>>>>>>> 6e23e69f09 (chore: bump curve25519-dalek from 3.2.1 to 4.1.3 (#2252)) "solana-sdk-macro", "thiserror", "wasm-bindgen", @@ -6137,7 +6162,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "siphasher", "solana-program", "solana-sdk-macro", @@ -6583,17 +6608,17 @@ dependencies = [ "bincode", "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "itertools 0.12.1", "lazy_static", "merlin", "num-derive", "num-traits", - "rand 0.7.3", + "rand 0.8.5", "serde", "serde_derive", "serde_json", - "sha3 0.9.1", + "sha3", "solana-program", "solana-sdk", "subtle", @@ -6623,17 +6648,17 @@ dependencies = [ "bytemuck", "bytemuck_derive", "byteorder 1.5.0", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "itertools 0.12.1", "lazy_static", "merlin", "num-derive", "num-traits", - "rand 0.7.3", + "rand 0.8.5", "serde", "serde_derive", "serde_json", - "sha3 0.9.1", + "sha3", "solana-curve25519", "solana-program", "solana-sdk", diff --git a/sdk/program/src/pubkey.rs b/sdk/program/src/pubkey.rs index 3ade0b1a4b2f69..7828c3e8cfae4d 100644 --- a/sdk/program/src/pubkey.rs +++ b/sdk/program/src/pubkey.rs @@ -171,9 +171,12 @@ impl TryFrom<&str> for Pubkey { pub fn bytes_are_curve_point>(_bytes: T) -> bool { #[cfg(not(target_os = "solana"))] { - curve25519_dalek::edwards::CompressedEdwardsY::from_slice(_bytes.as_ref()) - .decompress() - .is_some() + let Ok(compressed_edwards_y) = + curve25519_dalek::edwards::CompressedEdwardsY::from_slice(_bytes.as_ref()) + else { + return false; + }; + compressed_edwards_y.decompress().is_some() } #[cfg(target_os = "solana")] unimplemented!(); @@ -932,12 +935,7 @@ mod tests { if let Ok(program_address) = Pubkey::create_program_address(&[&bytes1, &bytes2], &program_id) { - let is_on_curve = curve25519_dalek::edwards::CompressedEdwardsY::from_slice( - &program_address.to_bytes(), - ) - .decompress() - .is_some(); - assert!(!is_on_curve); + assert!(!program_address.is_on_curve()); assert!(!addresses.contains(&program_address)); addresses.push(program_address); } diff --git a/zk-sdk/Cargo.toml b/zk-sdk/Cargo.toml index a57b994e017d2f..cfec8444de9aa6 100644 --- a/zk-sdk/Cargo.toml +++ b/zk-sdk/Cargo.toml @@ -28,11 +28,11 @@ bincode = { workspace = true } curve25519-dalek = { workspace = true, features = ["serde"] } itertools = { workspace = true } lazy_static = { workspace = true } -rand = { version = "0.7" } +rand = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } serde_json = { workspace = true } -sha3 = "0.9" +sha3 = { workspace = true } solana-sdk = { workspace = true } subtle = { workspace = true } zeroize = { workspace = true, features = ["zeroize_derive"] } diff --git a/zk-sdk/src/encryption/elgamal.rs b/zk-sdk/src/encryption/elgamal.rs index 3d950f75f6cc1b..0496a042fb6950 100644 --- a/zk-sdk/src/encryption/elgamal.rs +++ b/zk-sdk/src/encryption/elgamal.rs @@ -315,7 +315,7 @@ impl ElGamalPubkey { /// Derives the `ElGamalPubkey` that uniquely corresponds to an `ElGamalSecretKey`. pub fn new(secret: &ElGamalSecretKey) -> Self { let s = &secret.0; - assert!(s != &Scalar::zero()); + assert!(s != &Scalar::ZERO); ElGamalPubkey(s.invert() * &(*H)) } @@ -379,9 +379,12 @@ impl TryFrom<&[u8]> for ElGamalPubkey { if bytes.len() != ELGAMAL_PUBKEY_LEN { return Err(ElGamalError::PubkeyDeserialization); } + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return Err(ElGamalError::PubkeyDeserialization); + }; Ok(ElGamalPubkey( - CompressedRistretto::from_slice(bytes) + compressed_ristretto .decompress() .ok_or(ElGamalError::PubkeyDeserialization)?, )) @@ -550,6 +553,7 @@ impl TryFrom<&[u8]> for ElGamalSecretKey { match bytes.try_into() { Ok(bytes) => Ok(ElGamalSecretKey::from( Scalar::from_canonical_bytes(bytes) + .into_option() .ok_or(ElGamalError::SecretKeyDeserialization)?, )), _ => Err(ElGamalError::SecretKeyDeserialization), @@ -736,10 +740,11 @@ impl DecryptHandle { if bytes.len() != DECRYPT_HANDLE_LEN { return None; } + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return None; + }; - Some(DecryptHandle( - CompressedRistretto::from_slice(bytes).decompress()?, - )) + compressed_ristretto.decompress().map(DecryptHandle) } } diff --git a/zk-sdk/src/encryption/pedersen.rs b/zk-sdk/src/encryption/pedersen.rs index dfa6f93dcf5ec9..2dc20cb0b520bf 100644 --- a/zk-sdk/src/encryption/pedersen.rs +++ b/zk-sdk/src/encryption/pedersen.rs @@ -89,7 +89,9 @@ impl PedersenOpening { pub fn from_bytes(bytes: &[u8]) -> Option { match bytes.try_into() { - Ok(bytes) => Scalar::from_canonical_bytes(bytes).map(PedersenOpening), + Ok(bytes) => Scalar::from_canonical_bytes(bytes) + .into_option() + .map(PedersenOpening), _ => None, } } @@ -183,9 +185,11 @@ impl PedersenCommitment { return None; } - Some(PedersenCommitment( - CompressedRistretto::from_slice(bytes).decompress()?, - )) + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return None; + }; + + compressed_ristretto.decompress().map(PedersenCommitment) } } diff --git a/zk-sdk/src/range_proof/generators.rs b/zk-sdk/src/range_proof/generators.rs index f67baf5fef2d4b..f6071df3eb4526 100644 --- a/zk-sdk/src/range_proof/generators.rs +++ b/zk-sdk/src/range_proof/generators.rs @@ -4,14 +4,14 @@ use { digest::{ExtendableOutput, Update, XofReader}, ristretto::RistrettoPoint, }, - sha3::{Sha3XofReader, Shake256}, + sha3::{Shake256, Shake256Reader}, }; const MAX_GENERATOR_LENGTH: usize = u32::MAX as usize; /// Generators for Pedersen vector commitments that are used for inner-product proofs. struct GeneratorsChain { - reader: Sha3XofReader, + reader: Shake256Reader, } impl GeneratorsChain { diff --git a/zk-sdk/src/range_proof/inner_product.rs b/zk-sdk/src/range_proof/inner_product.rs index d45a38a9afa4ff..fef991817e016c 100644 --- a/zk-sdk/src/range_proof/inner_product.rs +++ b/zk-sdk/src/range_proof/inner_product.rs @@ -412,8 +412,10 @@ impl InnerProductProof { let pos = 2 * lg_n * 32; let a = Scalar::from_canonical_bytes(util::read32(&slice[pos..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let b = Scalar::from_canonical_bytes(util::read32(&slice[pos + 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; Ok(InnerProductProof { L_vec, R_vec, a, b }) @@ -441,7 +443,7 @@ mod tests { let b: Vec<_> = (0..n).map(|_| Scalar::random(&mut OsRng)).collect(); let c = util::inner_product(&a, &b).unwrap(); - let G_factors: Vec = iter::repeat(Scalar::one()).take(n).collect(); + let G_factors: Vec = iter::repeat(Scalar::ONE).take(n).collect(); let y_inv = Scalar::random(&mut OsRng); let H_factors: Vec = util::exp_iter(y_inv).take(n).collect(); @@ -478,7 +480,7 @@ mod tests { assert!(proof .verify( n, - iter::repeat(Scalar::one()).take(n), + iter::repeat(Scalar::ONE).take(n), util::exp_iter(y_inv).take(n), &P, &Q, @@ -493,7 +495,7 @@ mod tests { assert!(proof .verify( n, - iter::repeat(Scalar::one()).take(n), + iter::repeat(Scalar::ONE).take(n), util::exp_iter(y_inv).take(n), &P, &Q, diff --git a/zk-sdk/src/range_proof/mod.rs b/zk-sdk/src/range_proof/mod.rs index 9a4939845ae847..eacbb272e852a9 100644 --- a/zk-sdk/src/range_proof/mod.rs +++ b/zk-sdk/src/range_proof/mod.rs @@ -180,16 +180,16 @@ impl RangeProof { let mut i = 0; let mut exp_z = z * z; - let mut exp_y = Scalar::one(); + let mut exp_y = Scalar::ONE; for (amount_i, n_i) in amounts.iter().zip(bit_lengths.iter()) { - let mut exp_2 = Scalar::one(); + let mut exp_2 = Scalar::ONE; for j in 0..(*n_i) { // `j` is guaranteed to be at most `u64::BITS` (a 6-bit number) and therefore, // casting is lossless and right shift can be safely unwrapped let a_L_j = Scalar::from(amount_i.checked_shr(j as u32).unwrap() & 1); - let a_R_j = a_L_j - Scalar::one(); + let a_R_j = a_L_j - Scalar::ONE; l_poly.0[i] = a_L_j - z; l_poly.1[i] = s_L[i]; @@ -224,7 +224,7 @@ impl RangeProof { // z^2 * V_1 + z^3 * V_2 + ... + z^{m+1} * V_m + delta(y, z)*G + x*T_1 + x^2*T_2 let x = transcript.challenge_scalar(b"x"); - let mut agg_opening = Scalar::zero(); + let mut agg_opening = Scalar::ZERO; let mut exp_z = z; for opening in openings { exp_z *= z; @@ -255,7 +255,7 @@ impl RangeProof { let w = transcript.challenge_scalar(b"w"); let Q = w * &(*G); - let G_factors: Vec = iter::repeat(Scalar::one()).take(nm).collect(); + let G_factors: Vec = iter::repeat(Scalar::ONE).take(nm).collect(); let H_factors: Vec = util::exp_iter(y.invert()).take(nm).collect(); // generate challenge `c` for consistency with the verifier's transcript @@ -358,7 +358,7 @@ impl RangeProof { let value_commitment_scalars = util::exp_iter(z).take(m).map(|z_exp| c * zz * z_exp); let mega_check = RistrettoPoint::optional_multiscalar_mul( - iter::once(Scalar::one()) + iter::once(Scalar::ONE) .chain(iter::once(x)) .chain(iter::once(c * x)) .chain(iter::once(c * x * x)) @@ -421,10 +421,13 @@ impl RangeProof { let T_2 = CompressedRistretto(util::read32(&slice[3 * 32..])); let t_x = Scalar::from_canonical_bytes(util::read32(&slice[4 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let t_x_blinding = Scalar::from_canonical_bytes(util::read32(&slice[5 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let e_blinding = Scalar::from_canonical_bytes(util::read32(&slice[6 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let ipp_proof = InnerProductProof::from_bytes(&slice[7 * 32..])?; diff --git a/zk-sdk/src/range_proof/util.rs b/zk-sdk/src/range_proof/util.rs index 29af3821596cc3..fecaf8460381b7 100644 --- a/zk-sdk/src/range_proof/util.rs +++ b/zk-sdk/src/range_proof/util.rs @@ -9,7 +9,7 @@ pub struct VecPoly1(pub Vec, pub Vec); impl VecPoly1 { pub fn zero(n: usize) -> Self { - VecPoly1(vec![Scalar::zero(); n], vec![Scalar::zero(); n]) + VecPoly1(vec![Scalar::ZERO; n], vec![Scalar::ZERO; n]) } pub fn inner_product(&self, rhs: &VecPoly1) -> Option { @@ -30,7 +30,7 @@ impl VecPoly1 { pub fn eval(&self, x: Scalar) -> Vec { let n = self.0.len(); - let mut out = vec![Scalar::zero(); n]; + let mut out = vec![Scalar::ZERO; n]; #[allow(clippy::needless_range_loop)] for i in 0..n { out[i] = self.0[i] + self.1[i] * x; @@ -72,7 +72,7 @@ impl Iterator for ScalarExp { /// Return an iterator of the powers of `x`. pub fn exp_iter(x: Scalar) -> ScalarExp { - let next_exp_x = Scalar::one(); + let next_exp_x = Scalar::ONE; ScalarExp { x, next_exp_x } } @@ -81,7 +81,7 @@ pub fn add_vec(a: &[Scalar], b: &[Scalar]) -> Vec { // throw some error //println!("lengths of vectors don't match for vector addition"); } - let mut out = vec![Scalar::zero(); b.len()]; + let mut out = vec![Scalar::ZERO; b.len()]; for i in 0..a.len() { out[i] = a[i] + b[i]; } @@ -101,7 +101,7 @@ pub fn read32(data: &[u8]) -> [u8; 32] { /// \\] /// Errors if the lengths of \\(\mathbf{a}\\) and \\(\mathbf{b}\\) are not equal. pub fn inner_product(a: &[Scalar], b: &[Scalar]) -> Option { - let mut out = Scalar::zero(); + let mut out = Scalar::ZERO; if a.len() != b.len() { return None; } @@ -123,7 +123,7 @@ pub fn sum_of_powers(x: &Scalar, n: usize) -> Scalar { return Scalar::from(n as u64); } let mut m = n; - let mut result = Scalar::one() + x; + let mut result = Scalar::ONE + x; let mut factor = *x; while m > 2 { factor = factor * factor; diff --git a/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs b/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs index 9ff9529e4a52e8..1d5ad3243c15e1 100644 --- a/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs +++ b/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs @@ -189,7 +189,7 @@ impl CiphertextCiphertextEqualityProof { vec![ &self.z_s, // z_s &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z_x), // w * z_x &(&w * &self.z_s), // w * z_s &(&w_negated * &c), // -w * c diff --git a/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs b/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs index 341d8e5a3aee2b..3f5fc58e3e2799 100644 --- a/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs +++ b/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs @@ -176,7 +176,7 @@ impl CiphertextCommitmentEqualityProof { vec![ &self.z_s, // z_s &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z_x), // w * z_x &(&w * &self.z_s), // w * z_s &(&w_negated * &c), // -w * c diff --git a/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs b/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs index 2b5ecd44dc5843..688d3cf73d5c88 100644 --- a/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs +++ b/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs @@ -176,7 +176,7 @@ impl GroupedCiphertext2HandlesValidityProof { &self.z_r, // z_r &self.z_x, // z_x &(-&c), // -c - &-(&Scalar::one()), // -identity + &-(&Scalar::ONE), // -identity &(&w * &self.z_r), // w * z_r &(&w_negated * &c), // -w * c &w_negated, // -w diff --git a/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs b/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs index a825eabb6235af..ab917b6b7319ee 100644 --- a/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs +++ b/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs @@ -197,7 +197,7 @@ impl GroupedCiphertext3HandlesValidityProof { &self.z_r, // z_r &self.z_x, // z_x &(-&c), // -c - &-(&Scalar::one()), // -identity + &-(&Scalar::ONE), // -identity &(&w * &self.z_r), // w * z_r &(&w_negated * &c), // -w * c &w_negated, // -w diff --git a/zk-sdk/src/sigma_proofs/mod.rs b/zk-sdk/src/sigma_proofs/mod.rs index f6d6c8d9557890..c8b847a61399b3 100644 --- a/zk-sdk/src/sigma_proofs/mod.rs +++ b/zk-sdk/src/sigma_proofs/mod.rs @@ -66,10 +66,15 @@ use { fn ristretto_point_from_optional_slice( optional_slice: Option<&[u8]>, ) -> Result { - optional_slice - .and_then(|slice| (slice.len() == RISTRETTO_POINT_LEN).then_some(slice)) - .map(CompressedRistretto::from_slice) - .ok_or(SigmaProofVerificationError::Deserialization) + let Some(slice) = optional_slice else { + return Err(SigmaProofVerificationError::Deserialization); + }; + + if slice.len() != RISTRETTO_POINT_LEN { + return Err(SigmaProofVerificationError::Deserialization); + } + + CompressedRistretto::from_slice(slice).map_err(|_| SigmaProofVerificationError::Deserialization) } /// Deserializes an optional slice of bytes to a scalar. @@ -83,6 +88,6 @@ fn canonical_scalar_from_optional_slice( optional_slice .and_then(|slice| (slice.len() == SCALAR_LEN).then_some(slice)) // if chunk is the wrong length, convert to None .and_then(|slice| slice.try_into().ok()) // convert to array - .and_then(Scalar::from_canonical_bytes) + .and_then(|slice| Scalar::from_canonical_bytes(slice).into_option()) .ok_or(SigmaProofVerificationError::Deserialization) } diff --git a/zk-sdk/src/sigma_proofs/percentage_with_cap.rs b/zk-sdk/src/sigma_proofs/percentage_with_cap.rs index d53c118c858e53..0a1d5d33342f36 100644 --- a/zk-sdk/src/sigma_proofs/percentage_with_cap.rs +++ b/zk-sdk/src/sigma_proofs/percentage_with_cap.rs @@ -393,7 +393,7 @@ impl PercentageWithCapProof { c_max_proof, -c_max_proof * m, -z_max, - Scalar::one(), + Scalar::ONE, w * z_x, w * z_delta_real, -w * c_equality, diff --git a/zk-sdk/src/sigma_proofs/pubkey_validity.rs b/zk-sdk/src/sigma_proofs/pubkey_validity.rs index 97e6281e913d92..a6a72c2c2b6b8e 100644 --- a/zk-sdk/src/sigma_proofs/pubkey_validity.rs +++ b/zk-sdk/src/sigma_proofs/pubkey_validity.rs @@ -65,7 +65,7 @@ impl PubkeyValidityProof { // extract the relevant scalar and Ristretto points from the input let s = elgamal_keypair.secret().get_scalar(); - assert!(s != &Scalar::zero()); + assert!(s != &Scalar::ZERO); let s_inv = s.invert(); // generate a random masking factor that also serves as a nonce @@ -109,7 +109,7 @@ impl PubkeyValidityProof { .ok_or(SigmaProofVerificationError::Deserialization)?; let check = RistrettoPoint::vartime_multiscalar_mul( - vec![&self.z, &(-&c), &(-&Scalar::one())], + vec![&self.z, &(-&c), &(-&Scalar::ONE)], vec![&(*H), P, &Y], ); diff --git a/zk-sdk/src/sigma_proofs/zero_ciphertext.rs b/zk-sdk/src/sigma_proofs/zero_ciphertext.rs index 498758aaa9b295..f598210af6018b 100644 --- a/zk-sdk/src/sigma_proofs/zero_ciphertext.rs +++ b/zk-sdk/src/sigma_proofs/zero_ciphertext.rs @@ -136,7 +136,7 @@ impl ZeroCiphertextProof { vec![ &self.z, // z &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z), // w * z &(&w_negated * &c), // -w * c &w_negated, // -w diff --git a/zk-token-sdk/Cargo.toml b/zk-token-sdk/Cargo.toml index d466d2ba0af22d..428fe49c77d29a 100644 --- a/zk-token-sdk/Cargo.toml +++ b/zk-token-sdk/Cargo.toml @@ -30,11 +30,11 @@ curve25519-dalek = { workspace = true, features = ["serde"] } itertools = { workspace = true } lazy_static = { workspace = true } merlin = { workspace = true } -rand = { version = "0.7" } +rand = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } serde_json = { workspace = true } -sha3 = "0.9" +sha3 = { workspace = true } solana-sdk = { workspace = true } subtle = { workspace = true } zeroize = { workspace = true, features = ["zeroize_derive"] } diff --git a/zk-token-sdk/src/encryption/elgamal.rs b/zk-token-sdk/src/encryption/elgamal.rs index 130aacef669545..4780f06dbcc9e9 100644 --- a/zk-token-sdk/src/encryption/elgamal.rs +++ b/zk-token-sdk/src/encryption/elgamal.rs @@ -358,7 +358,7 @@ impl ElGamalPubkey { #[allow(non_snake_case)] pub fn new(secret: &ElGamalSecretKey) -> Self { let s = &secret.0; - assert!(s != &Scalar::zero()); + assert_ne!(s, &Scalar::ZERO); ElGamalPubkey(s.invert() * &(*H)) } @@ -377,10 +377,11 @@ impl ElGamalPubkey { if bytes.len() != ELGAMAL_PUBKEY_LEN { return None; } + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return None; + }; - Some(ElGamalPubkey( - CompressedRistretto::from_slice(bytes).decompress()?, - )) + compressed_ristretto.decompress().map(ElGamalPubkey) } /// Encrypts an amount under the public key. @@ -440,8 +441,12 @@ impl TryFrom<&[u8]> for ElGamalPubkey { return Err(ElGamalError::PubkeyDeserialization); } + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return Err(ElGamalError::PubkeyDeserialization); + }; + Ok(ElGamalPubkey( - CompressedRistretto::from_slice(bytes) + compressed_ristretto .decompress() .ok_or(ElGamalError::PubkeyDeserialization)?, )) @@ -552,7 +557,9 @@ impl ElGamalSecretKey { #[deprecated(since = "2.0.0", note = "please use `try_from()` instead")] pub fn from_bytes(bytes: &[u8]) -> Option { match bytes.try_into() { - Ok(bytes) => Scalar::from_canonical_bytes(bytes).map(ElGamalSecretKey), + Ok(bytes) => Scalar::from_canonical_bytes(bytes) + .map(ElGamalSecretKey) + .into(), _ => None, } } @@ -611,6 +618,7 @@ impl TryFrom<&[u8]> for ElGamalSecretKey { match bytes.try_into() { Ok(bytes) => Ok(ElGamalSecretKey::from( Scalar::from_canonical_bytes(bytes) + .into_option() .ok_or(ElGamalError::SecretKeyDeserialization)?, )), _ => Err(ElGamalError::SecretKeyDeserialization), @@ -799,9 +807,11 @@ impl DecryptHandle { return None; } - Some(DecryptHandle( - CompressedRistretto::from_slice(bytes).decompress()?, - )) + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return None; + }; + + compressed_ristretto.decompress().map(DecryptHandle) } } diff --git a/zk-token-sdk/src/encryption/pedersen.rs b/zk-token-sdk/src/encryption/pedersen.rs index 2de593771590e6..bb3f94e43a329d 100644 --- a/zk-token-sdk/src/encryption/pedersen.rs +++ b/zk-token-sdk/src/encryption/pedersen.rs @@ -99,7 +99,9 @@ impl PedersenOpening { pub fn from_bytes(bytes: &[u8]) -> Option { match bytes.try_into() { - Ok(bytes) => Scalar::from_canonical_bytes(bytes).map(PedersenOpening), + Ok(bytes) => Scalar::from_canonical_bytes(bytes) + .map(PedersenOpening) + .into(), _ => None, } } @@ -192,10 +194,11 @@ impl PedersenCommitment { if bytes.len() != PEDERSEN_COMMITMENT_LEN { return None; } + let Ok(compressed_ristretto) = CompressedRistretto::from_slice(bytes) else { + return None; + }; - Some(PedersenCommitment( - CompressedRistretto::from_slice(bytes).decompress()?, - )) + compressed_ristretto.decompress().map(PedersenCommitment) } } diff --git a/zk-token-sdk/src/instruction/zero_balance.rs b/zk-token-sdk/src/instruction/zero_balance.rs index 7671fb21cc4569..12edda8f89a0ff 100644 --- a/zk-token-sdk/src/instruction/zero_balance.rs +++ b/zk-token-sdk/src/instruction/zero_balance.rs @@ -1,7 +1,7 @@ //! The zero-balance proof instruction. //! //! A zero-balance proof is defined with respect to a twisted ElGamal ciphertext. The proof -//! certifies that a given ciphertext encrypts the message 0 in the field (`Scalar::zero()`). To +//! certifies that a given ciphertext encrypts the message 0 in the field (`Scalar::ZERO`). To //! generate the proof, a prover must provide the decryption key for the ciphertext. #[cfg(not(target_os = "solana"))] diff --git a/zk-token-sdk/src/range_proof/generators.rs b/zk-token-sdk/src/range_proof/generators.rs index da2dcbcf7cb734..17548511c62356 100644 --- a/zk-token-sdk/src/range_proof/generators.rs +++ b/zk-token-sdk/src/range_proof/generators.rs @@ -4,7 +4,7 @@ use { digest::{ExtendableOutput, Update, XofReader}, ristretto::RistrettoPoint, }, - sha3::{Sha3XofReader, Shake256}, + sha3::{Shake256, Shake256Reader}, }; #[cfg(not(target_os = "solana"))] @@ -12,7 +12,7 @@ const MAX_GENERATOR_LENGTH: usize = u32::MAX as usize; /// Generators for Pedersen vector commitments that are used for inner-product proofs. struct GeneratorsChain { - reader: Sha3XofReader, + reader: Shake256Reader, } impl GeneratorsChain { diff --git a/zk-token-sdk/src/range_proof/inner_product.rs b/zk-token-sdk/src/range_proof/inner_product.rs index 44e8e0674a3d6a..3360dcf8809fba 100644 --- a/zk-token-sdk/src/range_proof/inner_product.rs +++ b/zk-token-sdk/src/range_proof/inner_product.rs @@ -412,8 +412,10 @@ impl InnerProductProof { let pos = 2 * lg_n * 32; let a = Scalar::from_canonical_bytes(util::read32(&slice[pos..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let b = Scalar::from_canonical_bytes(util::read32(&slice[pos + 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; Ok(InnerProductProof { L_vec, R_vec, a, b }) @@ -442,7 +444,7 @@ mod tests { let b: Vec<_> = (0..n).map(|_| Scalar::random(&mut OsRng)).collect(); let c = util::inner_product(&a, &b).unwrap(); - let G_factors: Vec = iter::repeat(Scalar::one()).take(n).collect(); + let G_factors: Vec = iter::repeat(Scalar::ONE).take(n).collect(); let y_inv = Scalar::random(&mut OsRng); let H_factors: Vec = util::exp_iter(y_inv).take(n).collect(); @@ -479,7 +481,7 @@ mod tests { assert!(proof .verify( n, - iter::repeat(Scalar::one()).take(n), + iter::repeat(Scalar::ONE).take(n), util::exp_iter(y_inv).take(n), &P, &Q, @@ -494,7 +496,7 @@ mod tests { assert!(proof .verify( n, - iter::repeat(Scalar::one()).take(n), + iter::repeat(Scalar::ONE).take(n), util::exp_iter(y_inv).take(n), &P, &Q, diff --git a/zk-token-sdk/src/range_proof/mod.rs b/zk-token-sdk/src/range_proof/mod.rs index d7c7774d469baf..61783a3991adaf 100644 --- a/zk-token-sdk/src/range_proof/mod.rs +++ b/zk-token-sdk/src/range_proof/mod.rs @@ -149,16 +149,16 @@ impl RangeProof { let mut i = 0; let mut exp_z = z * z; - let mut exp_y = Scalar::one(); + let mut exp_y = Scalar::ONE; for (amount_i, n_i) in amounts.iter().zip(bit_lengths.iter()) { - let mut exp_2 = Scalar::one(); + let mut exp_2 = Scalar::ONE; for j in 0..(*n_i) { // `j` is guaranteed to be at most `u64::BITS` (a 6-bit number) and therefore, // casting is lossless and right shift can be safely unwrapped let a_L_j = Scalar::from(amount_i.checked_shr(j as u32).unwrap() & 1); - let a_R_j = a_L_j - Scalar::one(); + let a_R_j = a_L_j - Scalar::ONE; l_poly.0[i] = a_L_j - z; l_poly.1[i] = s_L[i]; @@ -193,7 +193,7 @@ impl RangeProof { // z^2 * V_1 + z^3 * V_2 + ... + z^{m+1} * V_m + delta(y, z)*G + x*T_1 + x^2*T_2 let x = transcript.challenge_scalar(b"x"); - let mut agg_opening = Scalar::zero(); + let mut agg_opening = Scalar::ZERO; let mut exp_z = z; for opening in openings { exp_z *= z; @@ -224,7 +224,7 @@ impl RangeProof { let w = transcript.challenge_scalar(b"w"); let Q = w * &(*G); - let G_factors: Vec = iter::repeat(Scalar::one()).take(nm).collect(); + let G_factors: Vec = iter::repeat(Scalar::ONE).take(nm).collect(); let H_factors: Vec = util::exp_iter(y.invert()).take(nm).collect(); // generate challenge `c` for consistency with the verifier's transcript @@ -325,7 +325,7 @@ impl RangeProof { let value_commitment_scalars = util::exp_iter(z).take(m).map(|z_exp| c * zz * z_exp); let mega_check = RistrettoPoint::optional_multiscalar_mul( - iter::once(Scalar::one()) + iter::once(Scalar::ONE) .chain(iter::once(x)) .chain(iter::once(c * x)) .chain(iter::once(c * x * x)) @@ -388,10 +388,13 @@ impl RangeProof { let T_2 = CompressedRistretto(util::read32(&slice[3 * 32..])); let t_x = Scalar::from_canonical_bytes(util::read32(&slice[4 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let t_x_blinding = Scalar::from_canonical_bytes(util::read32(&slice[5 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let e_blinding = Scalar::from_canonical_bytes(util::read32(&slice[6 * 32..])) + .into_option() .ok_or(RangeProofVerificationError::Deserialization)?; let ipp_proof = InnerProductProof::from_bytes(&slice[7 * 32..])?; diff --git a/zk-token-sdk/src/range_proof/util.rs b/zk-token-sdk/src/range_proof/util.rs index a656e73d8a03d9..2054829e3254b0 100644 --- a/zk-token-sdk/src/range_proof/util.rs +++ b/zk-token-sdk/src/range_proof/util.rs @@ -8,7 +8,7 @@ pub struct VecPoly1(pub Vec, pub Vec); impl VecPoly1 { pub fn zero(n: usize) -> Self { - VecPoly1(vec![Scalar::zero(); n], vec![Scalar::zero(); n]) + VecPoly1(vec![Scalar::ZERO; n], vec![Scalar::ZERO; n]) } pub fn inner_product(&self, rhs: &VecPoly1) -> Option { @@ -29,7 +29,7 @@ impl VecPoly1 { pub fn eval(&self, x: Scalar) -> Vec { let n = self.0.len(); - let mut out = vec![Scalar::zero(); n]; + let mut out = vec![Scalar::ZERO; n]; #[allow(clippy::needless_range_loop)] for i in 0..n { out[i] = self.0[i] + self.1[i] * x; @@ -71,7 +71,7 @@ impl Iterator for ScalarExp { /// Return an iterator of the powers of `x`. pub fn exp_iter(x: Scalar) -> ScalarExp { - let next_exp_x = Scalar::one(); + let next_exp_x = Scalar::ONE; ScalarExp { x, next_exp_x } } @@ -80,7 +80,7 @@ pub fn add_vec(a: &[Scalar], b: &[Scalar]) -> Vec { // throw some error //println!("lengths of vectors don't match for vector addition"); } - let mut out = vec![Scalar::zero(); b.len()]; + let mut out = vec![Scalar::ZERO; b.len()]; for i in 0..a.len() { out[i] = a[i] + b[i]; } @@ -100,7 +100,7 @@ pub fn read32(data: &[u8]) -> [u8; 32] { /// \\] /// Errors if the lengths of \\(\mathbf{a}\\) and \\(\mathbf{b}\\) are not equal. pub fn inner_product(a: &[Scalar], b: &[Scalar]) -> Option { - let mut out = Scalar::zero(); + let mut out = Scalar::ZERO; if a.len() != b.len() { return None; } @@ -122,7 +122,7 @@ pub fn sum_of_powers(x: &Scalar, n: usize) -> Scalar { return Scalar::from(n as u64); } let mut m = n; - let mut result = Scalar::one() + x; + let mut result = Scalar::ONE + x; let mut factor = *x; while m > 2 { factor = factor * factor; diff --git a/zk-token-sdk/src/sigma_proofs/ciphertext_ciphertext_equality_proof.rs b/zk-token-sdk/src/sigma_proofs/ciphertext_ciphertext_equality_proof.rs index 70a5de9c4c5efb..24fca4fa649791 100644 --- a/zk-token-sdk/src/sigma_proofs/ciphertext_ciphertext_equality_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/ciphertext_ciphertext_equality_proof.rs @@ -189,7 +189,7 @@ impl CiphertextCiphertextEqualityProof { vec![ &self.z_s, // z_s &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z_x), // w * z_x &(&w * &self.z_s), // w * z_s &(&w_negated * &c), // -w * c diff --git a/zk-token-sdk/src/sigma_proofs/ciphertext_commitment_equality_proof.rs b/zk-token-sdk/src/sigma_proofs/ciphertext_commitment_equality_proof.rs index 768b07b216cdbe..0b361ffbcf52c4 100644 --- a/zk-token-sdk/src/sigma_proofs/ciphertext_commitment_equality_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/ciphertext_commitment_equality_proof.rs @@ -177,7 +177,7 @@ impl CiphertextCommitmentEqualityProof { vec![ &self.z_s, // z_s &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z_x), // w * z_x &(&w * &self.z_s), // w * z_s &(&w_negated * &c), // -w * c diff --git a/zk-token-sdk/src/sigma_proofs/fee_proof.rs b/zk-token-sdk/src/sigma_proofs/fee_proof.rs index c3a431768f1226..7dbbce77589cce 100644 --- a/zk-token-sdk/src/sigma_proofs/fee_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/fee_proof.rs @@ -358,7 +358,7 @@ impl FeeSigmaProof { c_max_proof, -c_max_proof * m, -z_max, - Scalar::one(), + Scalar::ONE, w * z_x, w * z_delta_real, -w * c_equality, diff --git a/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_2.rs b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_2.rs index 1c1a57997e4740..bef2a4b6c73747 100644 --- a/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_2.rs +++ b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_2.rs @@ -172,7 +172,7 @@ impl GroupedCiphertext2HandlesValidityProof { &self.z_r, // z_r &self.z_x, // z_x &(-&c), // -c - &-(&Scalar::one()), // -identity + &-(&Scalar::ONE), // -identity &(&w * &self.z_r), // w * z_r &(&w_negated * &c), // -w * c &w_negated, // -w diff --git a/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_3.rs b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_3.rs index 1324292315a04c..9b9c533a35b9f3 100644 --- a/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_3.rs +++ b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof/handles_3.rs @@ -201,7 +201,7 @@ impl GroupedCiphertext3HandlesValidityProof { &self.z_r, // z_r &self.z_x, // z_x &(-&c), // -c - &-(&Scalar::one()), // -identity + &-(&Scalar::ONE), // -identity &(&w * &self.z_r), // w * z_r &(&w_negated * &c), // -w * c &w_negated, // -w diff --git a/zk-token-sdk/src/sigma_proofs/mod.rs b/zk-token-sdk/src/sigma_proofs/mod.rs index bad707157a8c33..38a6dde20816ca 100644 --- a/zk-token-sdk/src/sigma_proofs/mod.rs +++ b/zk-token-sdk/src/sigma_proofs/mod.rs @@ -36,10 +36,15 @@ use { fn ristretto_point_from_optional_slice( optional_slice: Option<&[u8]>, ) -> Result { - optional_slice - .and_then(|slice| (slice.len() == RISTRETTO_POINT_LEN).then_some(slice)) - .map(CompressedRistretto::from_slice) - .ok_or(SigmaProofVerificationError::Deserialization) + let Some(slice) = optional_slice else { + return Err(SigmaProofVerificationError::Deserialization); + }; + + if slice.len() != RISTRETTO_POINT_LEN { + return Err(SigmaProofVerificationError::Deserialization); + } + + CompressedRistretto::from_slice(slice).map_err(|_| SigmaProofVerificationError::Deserialization) } /// Deserializes an optional slice of bytes to a scalar. @@ -53,6 +58,6 @@ fn canonical_scalar_from_optional_slice( optional_slice .and_then(|slice| (slice.len() == SCALAR_LEN).then_some(slice)) // if chunk is the wrong length, convert to None .and_then(|slice| slice.try_into().ok()) // convert to array - .and_then(Scalar::from_canonical_bytes) + .and_then(|bytes| Scalar::from_canonical_bytes(bytes).into()) .ok_or(SigmaProofVerificationError::Deserialization) } diff --git a/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs b/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs index e0d80f2a528ef8..22540a9ad5c0d4 100644 --- a/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/pubkey_proof.rs @@ -65,7 +65,7 @@ impl PubkeyValidityProof { // extract the relevant scalar and Ristretto points from the input let s = elgamal_keypair.secret().get_scalar(); - assert!(s != &Scalar::zero()); + assert!(s != &Scalar::ZERO); let s_inv = s.invert(); // generate a random masking factor that also serves as a nonce @@ -109,7 +109,7 @@ impl PubkeyValidityProof { .ok_or(SigmaProofVerificationError::Deserialization)?; let check = RistrettoPoint::vartime_multiscalar_mul( - vec![&self.z, &(-&c), &(-&Scalar::one())], + vec![&self.z, &(-&c), &(-&Scalar::ONE)], vec![&(*H), P, &Y], ); diff --git a/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs b/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs index 3585978c76c1df..9a20cb4fefba34 100644 --- a/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/zero_balance_proof.rs @@ -136,7 +136,7 @@ impl ZeroBalanceProof { vec![ &self.z, // z &(-&c), // -c - &(-&Scalar::one()), // -identity + &(-&Scalar::ONE), // -identity &(&w * &self.z), // w * z &(&w_negated * &c), // -w * c &w_negated, // -w