From 0b4d7bc9c6055a7562efe55af1647405062f2de9 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 15 Oct 2022 21:00:09 +0000 Subject: [PATCH 1/7] Migrate note encryption to use prepared w-NAF APIs --- CHANGELOG.md | 5 +++- Cargo.toml | 2 +- benches/note_decryption.rs | 5 ++-- src/bundle.rs | 8 ++++--- src/keys.rs | 48 ++++++++++++++++++++++++++++++-------- src/note_encryption.rs | 14 ++++++----- src/spec.rs | 39 +++++++++++++++++++++++++++---- tests/builder.rs | 4 ++-- 8 files changed, 96 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 760b2742..6deb97bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,10 @@ and this project adheres to Rust's notion of ### Added - `orchard::Proof::add_to_batch` - `orchard::address::Address::diversifier` -- `orchard::keys::Diversifier::from_bytes` +- `orchard::keys:`: + - `Diversifier::from_bytes` + - `PreparedEphemeralPublicKey` + - `PreparedIncomingViewingKey` - `orchard::note`: - `RandomSeed` - `Note::{from_parts, rseed}` diff --git a/Cargo.toml b/Cargo.toml index cd6bf741..0c4ffeb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ bitvec = "1" blake2b_simd = "1" ff = "0.12" fpe = "0.5" -group = "0.12" +group = "0.12.1" halo2_gadgets = "0.2" halo2_proofs = "0.2" hex = "0.4" diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index cab432fe..5385e4eb 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -3,7 +3,7 @@ use orchard::{ builder::Builder, bundle::Flags, circuit::ProvingKey, - keys::{FullViewingKey, Scope, SpendingKey}, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note_encryption::{CompactAction, OrchardDomain}, value::NoteValue, Anchor, Bundle, @@ -21,6 +21,7 @@ fn bench_note_decryption(c: &mut Criterion) { let fvk = FullViewingKey::from(&SpendingKey::from_bytes([7; 32]).unwrap()); let valid_ivk = fvk.to_ivk(Scope::External); let recipient = valid_ivk.address_at(0u32); + let valid_ivk = PreparedIncomingViewingKey::new(&valid_ivk); // Compact actions don't have the full AEAD ciphertext, so ZIP 307 trial-decryption // relies on an invalid ivk resulting in random noise for which the note commitment @@ -39,7 +40,7 @@ fn bench_note_decryption(c: &mut Criterion) { let mut sk = [0; 32]; sk[..4].copy_from_slice(&i.to_le_bytes()); let fvk = FullViewingKey::from(&SpendingKey::from_bytes(sk).unwrap()); - fvk.to_ivk(Scope::External) + PreparedIncomingViewingKey::new(&fvk.to_ivk(Scope::External)) }) .collect(); diff --git a/src/bundle.rs b/src/bundle.rs index c70ca635..2e924fa9 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -17,7 +17,7 @@ use crate::{ address::Address, bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, circuit::{Instance, Proof, VerifyingKey}, - keys::{IncomingViewingKey, OutgoingViewingKey}, + keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, note::Note, note_encryption::OrchardDomain, primitives::redpallas::{self, Binding, SpendAuth}, @@ -290,7 +290,8 @@ impl Bundle { .filter_map(|(idx, action)| { let domain = OrchardDomain::for_action(action); keys.iter().find_map(move |ivk| { - try_note_decryption(&domain, ivk, action) + let prepared_ivk = PreparedIncomingViewingKey::new(ivk); + try_note_decryption(&domain, &prepared_ivk, action) .map(|(n, a, m)| (idx, ivk.clone(), n, a, m)) }) }) @@ -305,9 +306,10 @@ impl Bundle { action_idx: usize, key: &IncomingViewingKey, ) -> Option<(Note, Address, [u8; 512])> { + let prepared_ivk = PreparedIncomingViewingKey::new(key); self.actions.get(action_idx).and_then(move |action| { let domain = OrchardDomain::for_action(action); - try_note_decryption(&domain, key, action) + try_note_decryption(&domain, &prepared_ivk, action) }) } diff --git a/src/keys.rs b/src/keys.rs index e277264d..24145c23 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -20,8 +20,9 @@ use crate::{ address::Address, primitives::redpallas::{self, SpendAuth}, spec::{ - commit_ivk, diversify_hash, extract_p, ka_orchard, prf_nf, to_base, to_scalar, - NonIdentityPallasPoint, NonZeroPallasBase, NonZeroPallasScalar, PrfExpand, + commit_ivk, diversify_hash, extract_p, ka_orchard, ka_orchard_prepared, prf_nf, to_base, + to_scalar, NonIdentityPallasPoint, NonZeroPallasBase, NonZeroPallasScalar, + PreparedNonIdentityBase, PreparedNonZeroScalar, PrfExpand, }, zip32::{self, ChildIndex, ExtendedSpendingKey}, }; @@ -627,7 +628,8 @@ impl KeyAgreementPrivateKey { /// Returns the payment address for this key corresponding to the given diversifier. fn address(&self, d: Diversifier) -> Address { - let pk_d = DiversifiedTransmissionKey::derive_inner(self, &d); + let prepared_ivk = PreparedIncomingViewingKey::new_inner(&self); + let pk_d = DiversifiedTransmissionKey::derive(&prepared_ivk, &d); Address::from_parts(d, pk_d) } } @@ -704,6 +706,22 @@ impl IncomingViewingKey { } } +/// An Orchard incoming viewing key that has been precomputed for trial decryption. +#[derive(Clone, Debug)] +pub struct PreparedIncomingViewingKey(PreparedNonZeroScalar); + +impl PreparedIncomingViewingKey { + /// Performs the necessary precomputations to use an `IncomingViewingKey` for note + /// decryption. + pub fn new(ivk: &IncomingViewingKey) -> Self { + Self::new_inner(&ivk.ivk) + } + + fn new_inner(ivk: &KeyAgreementPrivateKey) -> Self { + Self(PreparedNonZeroScalar::new(&ivk.0)) + } +} + /// A key that provides the capability to recover outgoing transaction information from /// the block chain. /// @@ -753,13 +771,9 @@ impl DiversifiedTransmissionKey { /// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. /// /// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents - pub(crate) fn derive(ivk: &IncomingViewingKey, d: &Diversifier) -> Self { - Self::derive_inner(&ivk.ivk, d) - } - - fn derive_inner(ivk: &KeyAgreementPrivateKey, d: &Diversifier) -> Self { - let g_d = diversify_hash(d.as_array()); - DiversifiedTransmissionKey(ka_orchard(&ivk.0, &g_d)) + pub(crate) fn derive(ivk: &PreparedIncomingViewingKey, d: &Diversifier) -> Self { + let g_d = PreparedNonIdentityBase::new(diversify_hash(d.as_array())); + DiversifiedTransmissionKey(ka_orchard_prepared(&ivk.0, &g_d)) } /// $abst_P(bytes)$ @@ -841,6 +855,20 @@ impl EphemeralPublicKey { } } +/// A Sapling ephemeral public key that has been precomputed for trial decryption. +#[derive(Clone, Debug)] +pub struct PreparedEphemeralPublicKey(PreparedNonIdentityBase); + +impl PreparedEphemeralPublicKey { + pub(crate) fn new(epk: EphemeralPublicKey) -> Self { + PreparedEphemeralPublicKey(PreparedNonIdentityBase::new(epk.0)) + } + + pub(crate) fn agree(&self, ivk: &PreparedIncomingViewingKey) -> SharedSecret { + SharedSecret(ka_orchard_prepared(&ivk.0, &self.0)) + } +} + /// $\mathsf{KA}^\mathsf{Orchard}.\mathsf{SharedSecret} := \mathbb{P}^{\ast}$ /// /// Defined in [section 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement]. diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 0b249eec..762cc560 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -14,7 +14,7 @@ use crate::{ action::Action, keys::{ DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, - IncomingViewingKey, OutgoingViewingKey, SharedSecret, + OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, }, note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, spec::diversify_hash, @@ -102,13 +102,13 @@ impl OrchardDomain { impl Domain for OrchardDomain { type EphemeralSecretKey = EphemeralSecretKey; type EphemeralPublicKey = EphemeralPublicKey; - type PreparedEphemeralPublicKey = EphemeralPublicKey; + type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; type SharedSecret = SharedSecret; type SymmetricKey = Hash; type Note = Note; type Recipient = Address; type DiversifiedTransmissionKey = DiversifiedTransmissionKey; - type IncomingViewingKey = IncomingViewingKey; + type IncomingViewingKey = PreparedIncomingViewingKey; type OutgoingViewingKey = OutgoingViewingKey; type ValueCommitment = ValueCommitment; type ExtractedCommitment = ExtractedNoteCommitment; @@ -124,7 +124,7 @@ impl Domain for OrchardDomain { } fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { - epk + PreparedEphemeralPublicKey::new(epk) } fn ka_derive_public( @@ -352,7 +352,7 @@ mod tests { action::Action, keys::{ DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, - OutgoingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, }, note::{ExtractedNoteCommitment, Nullifier, RandomSeed, TransmittedNoteCiphertext}, primitives::redpallas, @@ -370,7 +370,9 @@ mod tests { // // Recipient key material - let ivk = IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(); + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); let ovk = OutgoingViewingKey::from(tv.ovk); let d = Diversifier::from_bytes(tv.default_d); let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); diff --git a/src/spec.rs b/src/spec.rs index 67f7a7c4..ab5413ae 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -4,8 +4,7 @@ use core::iter; use core::ops::Deref; use ff::{Field, PrimeField, PrimeFieldBits}; -use group::GroupEncoding; -use group::{Curve, Group}; +use group::{Curve, Group, GroupEncoding, WnafBase, WnafScalar}; use halo2_gadgets::{poseidon::primitives as poseidon, sinsemilla::primitives as sinsemilla}; use halo2_proofs::arithmetic::{CurveAffine, CurveExt, FieldExt}; use pasta_curves::pallas; @@ -140,6 +139,26 @@ impl Deref for NonZeroPallasScalar { } } +const PREPARED_WINDOW_SIZE: usize = 4; + +#[derive(Clone, Debug)] +pub(crate) struct PreparedNonIdentityBase(WnafBase); + +impl PreparedNonIdentityBase { + pub(crate) fn new(base: NonIdentityPallasPoint) -> Self { + PreparedNonIdentityBase(WnafBase::new(base.0)) + } +} + +#[derive(Clone, Debug)] +pub(crate) struct PreparedNonZeroScalar(WnafScalar); + +impl PreparedNonZeroScalar { + pub(crate) fn new(scalar: &NonZeroPallasScalar) -> Self { + PreparedNonZeroScalar(WnafScalar::new(scalar)) + } +} + /// $\mathsf{ToBase}^\mathsf{Orchard}(x) := LEOS2IP_{\ell_\mathsf{PRFexpand}}(x) (mod q_P)$ /// /// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. @@ -213,8 +232,20 @@ pub(crate) fn ka_orchard( sk: &NonZeroPallasScalar, b: &NonIdentityPallasPoint, ) -> NonIdentityPallasPoint { - let mut wnaf = group::Wnaf::new(); - NonIdentityPallasPoint(wnaf.scalar(sk.deref()).base(*b.deref())) + ka_orchard_prepared( + &PreparedNonZeroScalar::new(sk), + &PreparedNonIdentityBase::new(*b), + ) +} + +/// Defined in [Zcash Protocol Spec § 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement]. +/// +/// [concreteorchardkeyagreement]: https://zips.z.cash/protocol/nu5.pdf#concreteorchardkeyagreement +pub(crate) fn ka_orchard_prepared( + sk: &PreparedNonZeroScalar, + b: &PreparedNonIdentityBase, +) -> NonIdentityPallasPoint { + NonIdentityPallasPoint(&b.0 * &sk.0) } /// Coordinate extractor for Pallas. diff --git a/tests/builder.rs b/tests/builder.rs index 35c53976..f9b0f271 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -3,7 +3,7 @@ use orchard::{ builder::Builder, bundle::{Authorized, Flags}, circuit::{ProvingKey, VerifyingKey}, - keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::ExtractedNoteCommitment, note_encryption::OrchardDomain, tree::{MerkleHashOrchard, MerklePath}, @@ -57,7 +57,7 @@ fn bundle_chain() { // Create a shielded bundle spending the previous output. let shielded_bundle: Bundle<_, i64> = { - let ivk = fvk.to_ivk(Scope::External); + let ivk = PreparedIncomingViewingKey::new(&fvk.to_ivk(Scope::External)); let (note, _, _) = shielding_bundle .actions() .iter() From 050b2f231ef59064843ea7f940da423a55556fa2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 15 Oct 2022 23:29:06 +0000 Subject: [PATCH 2/7] Add `memuse::DynamicUsage` impls for types used for batch scanning --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- src/keys.rs | 10 ++++++++++ src/note/nullifier.rs | 4 ++++ src/note_encryption.rs | 10 ++++++++++ src/spec.rs | 11 +++++++++++ 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6deb97bc..2b164e00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to Rust's notion of - `orchard::note`: - `RandomSeed` - `Note::{from_parts, rseed}` + - `impl memuse::DynamicUsage for Nullifier` +- `orchard::note_encryption`: + - `impl memuse::DynamicUsage for OrchardDomain` - `orchard::builder::SpendInfo::new` - `orchard::circuit::Circuit::from_action_context` diff --git a/Cargo.toml b/Cargo.toml index 0c4ffeb5..87490630 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,12 +28,12 @@ bitvec = "1" blake2b_simd = "1" ff = "0.12" fpe = "0.5" -group = "0.12.1" +group = { version = "0.12.1", features = ["wnaf-memuse"] } halo2_gadgets = "0.2" halo2_proofs = "0.2" hex = "0.4" lazy_static = "1" -memuse = { version = "0.2", features = ["nonempty"] } +memuse = { version = "0.2.1", features = ["nonempty"] } pasta_curves = "0.4" proptest = { version = "1.0.0", optional = true } rand = "0.8" diff --git a/src/keys.rs b/src/keys.rs index 24145c23..8224a1ca 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -710,6 +710,16 @@ impl IncomingViewingKey { #[derive(Clone, Debug)] pub struct PreparedIncomingViewingKey(PreparedNonZeroScalar); +impl memuse::DynamicUsage for PreparedIncomingViewingKey { + fn dynamic_usage(&self) -> usize { + self.0.dynamic_usage() + } + + fn dynamic_usage_bounds(&self) -> (usize, Option) { + self.0.dynamic_usage_bounds() + } +} + impl PreparedIncomingViewingKey { /// Performs the necessary precomputations to use an `IncomingViewingKey` for note /// decryption. diff --git a/src/note/nullifier.rs b/src/note/nullifier.rs index 74efe5cd..591ea655 100644 --- a/src/note/nullifier.rs +++ b/src/note/nullifier.rs @@ -1,5 +1,6 @@ use group::{ff::PrimeField, Group}; use halo2_proofs::arithmetic::CurveExt; +use memuse::DynamicUsage; use pasta_curves::pallas; use rand::RngCore; use subtle::CtOption; @@ -14,6 +15,9 @@ use crate::{ #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Nullifier(pub(crate) pallas::Base); +// We know that `pallas::Base` doesn't allocate internally. +memuse::impl_no_dynamic_usage!(Nullifier); + impl Nullifier { /// Generates a dummy nullifier for use as $\rho$ in dummy spent notes. /// diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 762cc560..8ad06c8a 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -85,6 +85,16 @@ pub struct OrchardDomain { rho: Nullifier, } +impl memuse::DynamicUsage for OrchardDomain { + fn dynamic_usage(&self) -> usize { + self.rho.dynamic_usage() + } + + fn dynamic_usage_bounds(&self) -> (usize, Option) { + self.rho.dynamic_usage_bounds() + } +} + impl OrchardDomain { /// Constructs a domain that can be used to trial-decrypt this action's output note. pub fn for_action(act: &Action) -> Self { diff --git a/src/spec.rs b/src/spec.rs index ab5413ae..3af8b97d 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -7,6 +7,7 @@ use ff::{Field, PrimeField, PrimeFieldBits}; use group::{Curve, Group, GroupEncoding, WnafBase, WnafScalar}; use halo2_gadgets::{poseidon::primitives as poseidon, sinsemilla::primitives as sinsemilla}; use halo2_proofs::arithmetic::{CurveAffine, CurveExt, FieldExt}; +use memuse::DynamicUsage; use pasta_curves::pallas; use subtle::{ConditionallySelectable, CtOption}; @@ -153,6 +154,16 @@ impl PreparedNonIdentityBase { #[derive(Clone, Debug)] pub(crate) struct PreparedNonZeroScalar(WnafScalar); +impl DynamicUsage for PreparedNonZeroScalar { + fn dynamic_usage(&self) -> usize { + self.0.dynamic_usage() + } + + fn dynamic_usage_bounds(&self) -> (usize, Option) { + self.0.dynamic_usage_bounds() + } +} + impl PreparedNonZeroScalar { pub(crate) fn new(scalar: &NonZeroPallasScalar) -> Self { PreparedNonZeroScalar(WnafScalar::new(scalar)) From b988d4c27551e1bed0896322a1e6ddfb95b40cce Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Oct 2022 02:45:24 +0100 Subject: [PATCH 3/7] Fix comment that incorrectly referred to Sapling when Orchard was meant --- src/keys.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keys.rs b/src/keys.rs index 8224a1ca..6182fc42 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -865,7 +865,7 @@ impl EphemeralPublicKey { } } -/// A Sapling ephemeral public key that has been precomputed for trial decryption. +/// An Orchard ephemeral public key that has been precomputed for trial decryption. #[derive(Clone, Debug)] pub struct PreparedEphemeralPublicKey(PreparedNonIdentityBase); From 786d285987ad51af3d6d9486bc81514cfb1d22cf Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Oct 2022 19:17:15 +0100 Subject: [PATCH 4/7] Fix a clippy lint. Signed-off-by: Daira Hopwood --- src/keys.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keys.rs b/src/keys.rs index 6182fc42..a7856f91 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -628,7 +628,7 @@ impl KeyAgreementPrivateKey { /// Returns the payment address for this key corresponding to the given diversifier. fn address(&self, d: Diversifier) -> Address { - let prepared_ivk = PreparedIncomingViewingKey::new_inner(&self); + let prepared_ivk = PreparedIncomingViewingKey::new_inner(self); let pk_d = DiversifiedTransmissionKey::derive(&prepared_ivk, &d); Address::from_parts(d, pk_d) } From cb1733d6adfe74e163b6a29410e16a0d649b74ad Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Oct 2022 19:27:56 +0100 Subject: [PATCH 5/7] Change number of iterations for the compact-note-decryption benchmark to 10240. This improves the accuracy by ensuring a more even distribution of more expensive decryptions. Signed-off-by: Daira Hopwood --- benches/note_decryption.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 5385e4eb..3ebbc6ed 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -32,10 +32,10 @@ fn bench_note_decryption(c: &mut Criterion) { // // Our fixed (action, invalid ivk) tuple will always fall into a specific rejection // case. In order to reflect the real behaviour in the benchmarks, we trial-decrypt - // with 1000 invalid ivks (each of which will result in a different uniformly-random - // plaintext); this is equivalent to trial-decrypting 1000 different actions with the + // with 10240 invalid ivks (each of which will result in a different uniformly-random + // plaintext); this is equivalent to trial-decrypting 10240 different actions with the // same ivk, but is faster to set up. - let invalid_ivks: Vec<_> = (0u32..1000) + let invalid_ivks: Vec<_> = (0u32..10240) .map(|i| { let mut sk = [0; 32]; sk[..4].copy_from_slice(&i.to_le_bytes()); From 7080c37532d0578dfbfdde938a7c0a1afd3c1adf Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 18 Oct 2022 12:37:12 -0600 Subject: [PATCH 6/7] Prepare keys only once in decrypt_outputs_with_keys --- src/bundle.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bundle.rs b/src/bundle.rs index 2e924fa9..239cce7c 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -284,15 +284,18 @@ impl Bundle { &self, keys: &[IncomingViewingKey], ) -> Vec<(usize, IncomingViewingKey, Note, Address, [u8; 512])> { + let prepared_keys: Vec<_> = keys + .iter() + .map(|ivk| (ivk, PreparedIncomingViewingKey::new(ivk))) + .collect(); self.actions .iter() .enumerate() .filter_map(|(idx, action)| { let domain = OrchardDomain::for_action(action); - keys.iter().find_map(move |ivk| { - let prepared_ivk = PreparedIncomingViewingKey::new(ivk); - try_note_decryption(&domain, &prepared_ivk, action) - .map(|(n, a, m)| (idx, ivk.clone(), n, a, m)) + prepared_keys.iter().find_map(|(ivk, prepared_ivk)| { + try_note_decryption(&domain, prepared_ivk, action) + .map(|(n, a, m)| (idx, (*ivk).clone(), n, a, m)) }) }) .collect() From 4c9b2096dc47d26d1d4632f634738f6938508962 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 18 Oct 2022 12:38:41 -0600 Subject: [PATCH 7/7] Fix beta clippy complaints. --- CHANGELOG.md | 3 +++ src/value.rs | 2 +- src/zip32.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b164e00..c9637be5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ and this project adheres to Rust's notion of - `impl memuse::DynamicUsage for OrchardDomain` - `orchard::builder::SpendInfo::new` - `orchard::circuit::Circuit::from_action_context` +- impls of `Eq` for: + - `orchard::zip32::ChildIndex` + - `orchard::value::ValueSum` ### Changed - Migrated to `zcash_note_encryption 0.2`. diff --git a/src/value.rs b/src/value.rs index 71727577..8b53fe16 100644 --- a/src/value.rs +++ b/src/value.rs @@ -144,7 +144,7 @@ pub(crate) enum Sign { } /// A sum of Orchard note values. -#[derive(Clone, Copy, Debug, Default, PartialEq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct ValueSum(i128); impl ValueSum { diff --git a/src/zip32.rs b/src/zip32.rs index ab0d30b3..3ba8bd57 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -65,7 +65,7 @@ impl FvkTag { } /// A hardened child index for a derived key. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct ChildIndex(u32); impl TryFrom for ChildIndex {