From 29e28d4e5eff3b9fc6d32983064080d8fdf4d7a0 Mon Sep 17 00:00:00 2001 From: yihau Date: Wed, 10 Jul 2024 18:07:08 +0800 Subject: [PATCH 1/7] bump curve25519-dalek from 3.2.1 to 4.1.3 --- .../scripts/downstream-project-spl-common.sh | 8 ++ Cargo.lock | 88 +++++++++++-------- Cargo.toml | 35 +------- curves/curve25519/src/edwards.rs | 12 ++- curves/curve25519/src/ristretto.rs | 12 ++- curves/curve25519/src/scalar.rs | 8 +- perf/src/sigverify.rs | 4 +- programs/sbf/Cargo.lock | 77 +++++++++------- sdk/program/src/pubkey.rs | 16 ++-- zk-sdk/Cargo.toml | 4 +- zk-sdk/src/encryption/elgamal.rs | 15 ++-- zk-sdk/src/encryption/pedersen.rs | 12 ++- zk-sdk/src/range_proof/generators.rs | 4 +- zk-sdk/src/range_proof/inner_product.rs | 8 +- zk-sdk/src/range_proof/mod.rs | 15 ++-- zk-sdk/src/range_proof/util.rs | 12 +-- .../ciphertext_ciphertext_equality.rs | 2 +- .../ciphertext_commitment_equality.rs | 2 +- .../grouped_ciphertext_validity/handles_2.rs | 2 +- .../grouped_ciphertext_validity/handles_3.rs | 2 +- zk-sdk/src/sigma_proofs/mod.rs | 15 ++-- .../src/sigma_proofs/percentage_with_cap.rs | 2 +- zk-sdk/src/sigma_proofs/pubkey_validity.rs | 4 +- zk-sdk/src/sigma_proofs/zero_ciphertext.rs | 2 +- zk-token-sdk/Cargo.toml | 4 +- zk-token-sdk/src/encryption/elgamal.rs | 28 ++++-- zk-token-sdk/src/encryption/pedersen.rs | 11 ++- zk-token-sdk/src/instruction/zero_balance.rs | 2 +- zk-token-sdk/src/range_proof/generators.rs | 4 +- zk-token-sdk/src/range_proof/inner_product.rs | 8 +- zk-token-sdk/src/range_proof/mod.rs | 15 ++-- zk-token-sdk/src/range_proof/util.rs | 12 +-- .../ciphertext_ciphertext_equality_proof.rs | 2 +- .../ciphertext_commitment_equality_proof.rs | 2 +- zk-token-sdk/src/sigma_proofs/fee_proof.rs | 2 +- .../handles_2.rs | 2 +- .../handles_3.rs | 2 +- zk-token-sdk/src/sigma_proofs/mod.rs | 15 ++-- zk-token-sdk/src/sigma_proofs/pubkey_proof.rs | 4 +- .../src/sigma_proofs/zero_balance_proof.rs | 2 +- 40 files changed, 267 insertions(+), 209 deletions(-) diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index 779af8f2568110..4280f1215bf072 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -27,3 +27,11 @@ 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/client/Cargo.toml +sed -i "s/^curve25519-dalek =.*/curve25519-dalek = \"4.1.3\"/" token/confidential-transfer/proof-generation/Cargo.toml + +# ignore these tests temporarily. see: https://github.com/anza-xyz/agave/pull/1693#issuecomment-2182615788 +sed -i 's/\([ \t]*\)async_trial!(confidential_transfer,/\1\/\/ async_trial!(confidential_transfer,/' token/cli/tests/command.rs +sed -i '/async fn confidential_transfer_transfer_with_fee_and_split_proof_context_in_parallel(/i #[ignore]' token/program-2022-test/tests/confidential_transfer.rs diff --git a/Cargo.lock b/Cargo.lock index 50235b9769c27c..8acf626c030ebe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -951,7 +951,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", @@ -963,7 +963,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", ] @@ -985,12 +984,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" @@ -1746,16 +1739,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" @@ -2010,7 +2032,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", @@ -2185,6 +2207,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" @@ -5277,18 +5305,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" @@ -6273,7 +6289,7 @@ version = "2.1.0" dependencies = [ "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-program", "thiserror", ] @@ -6866,7 +6882,7 @@ dependencies = [ "bincode", "bv", "caps", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "dlopen2", "fnv", "lazy_static", @@ -6957,7 +6973,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", @@ -6978,7 +6994,7 @@ dependencies = [ "serde_json", "serial_test", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "solana-atomic-u64", "solana-decode-error", "solana-define-syscall", @@ -7439,7 +7455,7 @@ dependencies = [ "bytemuck_derive", "byteorder", "chrono", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "derivation-path", "digest 0.10.7", "ed25519-dalek", @@ -7469,7 +7485,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "siphasher", "solana-bn254", "solana-decode-error", @@ -8202,17 +8218,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", @@ -8227,7 +8243,7 @@ version = "2.1.0" dependencies = [ "bytemuck", "criterion", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "num-derive", "num-traits", "solana-log-collector", @@ -8241,7 +8257,7 @@ name = "solana-zk-token-proof-program-tests" version = "2.1.0" dependencies = [ "bytemuck", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-compute-budget", "solana-program-test", "solana-sdk", @@ -8258,17 +8274,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 fe3592daaa5042..672922e484a7a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -220,7 +220,7 @@ criterion-stats = "0.3.0" crossbeam-channel = "0.5.13" csv = "1.3.0" ctrlc = "3.4.5" -curve25519-dalek = "3.2.1" +curve25519-dalek = { version = "4.1.3", features = ["digest", "rand_core"] } dashmap = "5.5.3" derivation-path = { version = "0.2.0", default-features = false } derivative = "2.2.0" @@ -543,39 +543,6 @@ 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" - # Solana RPC nodes experience stalls when running with `tokio` containing this # commit: # https://github.com/tokio-rs/tokio/commit/4eed411519783ef6f58cbf74f886f91142b5cfa6 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 e10675270471ea..d58f27879ba393 100644 --- a/perf/src/sigverify.rs +++ b/perf/src/sigverify.rs @@ -1276,7 +1276,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()); @@ -1311,7 +1311,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 e2d707ac3271ce..62d577f3ae8859 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -709,7 +709,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", "generic-array", ] @@ -722,12 +721,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" @@ -1219,11 +1212,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" @@ -1461,7 +1482,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", @@ -1639,6 +1660,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" @@ -4368,18 +4395,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" @@ -4977,7 +4992,7 @@ version = "2.1.0" dependencies = [ "bytemuck", "bytemuck_derive", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "solana-program", "thiserror", ] @@ -5320,7 +5335,7 @@ dependencies = [ "bincode", "bv", "caps", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "dlopen2", "fnv", "lazy_static", @@ -5379,7 +5394,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", @@ -5394,7 +5409,7 @@ dependencies = [ "serde_bytes", "serde_derive", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "solana-atomic-u64", "solana-decode-error", "solana-define-syscall", @@ -6272,7 +6287,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.8", - "sha3 0.10.8", + "sha3", "siphasher", "solana-bn254", "solana-decode-error", @@ -6768,17 +6783,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", @@ -6809,17 +6824,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 5d3433c1247f90..1c1dcaed092544 100644 --- a/sdk/program/src/pubkey.rs +++ b/sdk/program/src/pubkey.rs @@ -172,9 +172,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!(); @@ -933,12 +936,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 236c7a5e06dbf3..c7ffa7569e0069 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 c0d90fb148d26c..2ba02df21c9d5d 100644 --- a/zk-sdk/src/encryption/elgamal.rs +++ b/zk-sdk/src/encryption/elgamal.rs @@ -316,7 +316,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)) } @@ -380,9 +380,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)?, )) @@ -551,6 +554,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), @@ -737,10 +741,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 901f4f83027a41..42bacbec55e71e 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 3cae18a8bb0f3c..fb2431dfa1d5ae 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 910d0a9a3ea556..319a889b760681 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 18a8e1efe5cadb..64e2b1794753d8 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 4166a543b77e76..5e3c08f5b0630a 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 cc4f785550a73b..20d43f998f2eaa 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 e90b98920abfd4..d0fcaf8b48bd41 100644 --- a/zk-token-sdk/src/encryption/elgamal.rs +++ b/zk-token-sdk/src/encryption/elgamal.rs @@ -359,7 +359,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)) } @@ -378,10 +378,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. @@ -441,8 +442,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)?, )) @@ -553,7 +558,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, } } @@ -612,6 +619,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), @@ -800,9 +808,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 b33ce32001a359..f452cd74dde376 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 32dac961f507df..200194e8079abd 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 565ba9b4360920..0c296fc2df6477 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 5cb67553e26276..308570ad45b4b6 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 be45e969cf1257..e72e1c0c4d94a1 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 16f6c3b25d81ef..2498a1e68686b5 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 From a601fc3999c0610c38fb7b0dd7d591de479dbc5c Mon Sep 17 00:00:00 2001 From: Yihau Chen Date: Fri, 30 Aug 2024 11:47:27 +0800 Subject: [PATCH 2/7] Update .github/scripts/downstream-project-spl-common.sh Co-authored-by: samkim-crypto --- .github/scripts/downstream-project-spl-common.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index 4280f1215bf072..2a2944a92e0eda 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -29,7 +29,6 @@ fi 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/client/Cargo.toml sed -i "s/^curve25519-dalek =.*/curve25519-dalek = \"4.1.3\"/" token/confidential-transfer/proof-generation/Cargo.toml # ignore these tests temporarily. see: https://github.com/anza-xyz/agave/pull/1693#issuecomment-2182615788 From 038e1b9c46d201291ce81c9d46a0b76f1cbeff68 Mon Sep 17 00:00:00 2001 From: Yihau Chen Date: Fri, 30 Aug 2024 11:47:32 +0800 Subject: [PATCH 3/7] Update .github/scripts/downstream-project-spl-common.sh Co-authored-by: samkim-crypto --- .github/scripts/downstream-project-spl-common.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index 2a2944a92e0eda..e70c10d070b7e9 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -30,7 +30,3 @@ sed -i 's/solana-geyser-plugin-interface/agave-geyser-plugin-interface/g' ./Carg # 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 - -# ignore these tests temporarily. see: https://github.com/anza-xyz/agave/pull/1693#issuecomment-2182615788 -sed -i 's/\([ \t]*\)async_trial!(confidential_transfer,/\1\/\/ async_trial!(confidential_transfer,/' token/cli/tests/command.rs -sed -i '/async fn confidential_transfer_transfer_with_fee_and_split_proof_context_in_parallel(/i #[ignore]' token/program-2022-test/tests/confidential_transfer.rs From bd07e436a7aa2adbaa93529f874b066a8799a39f Mon Sep 17 00:00:00 2001 From: Yihau Chen Date: Fri, 30 Aug 2024 11:47:58 +0800 Subject: [PATCH 4/7] Update .github/scripts/downstream-project-spl-common.sh Co-authored-by: samkim-crypto --- .github/scripts/downstream-project-spl-common.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index e70c10d070b7e9..9de43071976f05 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -25,6 +25,9 @@ fi ./patch.crates-io.sh "$SOLANA_DIR" +echo "[profile.dev.package.curve25519-dalek] +opt-level = 3" >> Cargo.toml + # 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 From 6e1edbe19bd370bed8eae5e68a9322fc34f72577 Mon Sep 17 00:00:00 2001 From: Yihau Chen Date: Fri, 30 Aug 2024 11:48:05 +0800 Subject: [PATCH 5/7] Update Cargo.toml Co-authored-by: samkim-crypto --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 672922e484a7a9..a7b99a42dc5eb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -543,6 +543,9 @@ solana-program = { path = "sdk/program" } solana-zk-sdk = { path = "zk-sdk" } solana-zk-token-sdk = { path = "zk-token-sdk" } +[profile.dev.package.curve25519-dalek] +opt-level = 3 + # Solana RPC nodes experience stalls when running with `tokio` containing this # commit: # https://github.com/tokio-rs/tokio/commit/4eed411519783ef6f58cbf74f886f91142b5cfa6 From f1d41687ea3d3b17579d393d3a7608115aac7822 Mon Sep 17 00:00:00 2001 From: yihau Date: Sun, 1 Sep 2024 14:32:52 +0800 Subject: [PATCH 6/7] remove opt level hack --- .github/scripts/downstream-project-spl-common.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/scripts/downstream-project-spl-common.sh b/.github/scripts/downstream-project-spl-common.sh index 9de43071976f05..e70c10d070b7e9 100644 --- a/.github/scripts/downstream-project-spl-common.sh +++ b/.github/scripts/downstream-project-spl-common.sh @@ -25,9 +25,6 @@ fi ./patch.crates-io.sh "$SOLANA_DIR" -echo "[profile.dev.package.curve25519-dalek] -opt-level = 3" >> Cargo.toml - # 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 From 7ba52fa8f820e60b78186d76537a3bc061758af4 Mon Sep 17 00:00:00 2001 From: yihau Date: Sun, 1 Sep 2024 15:01:45 +0800 Subject: [PATCH 7/7] add comment for opt level --- Cargo.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index a7b99a42dc5eb3..439312bb0fd75c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -543,6 +543,14 @@ solana-program = { path = "sdk/program" } solana-zk-sdk = { path = "zk-sdk" } solana-zk-token-sdk = { path = "zk-token-sdk" } +# 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