Use prepared epks and ivks in trial decryption.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2022-09-23 22:02:01 +01:00
parent b0eeb1a188
commit e57e799170
4 changed files with 137 additions and 82 deletions

View File

@ -6,7 +6,17 @@ replace-with = "vendored-sources"
[source."https://github.com/zcash/librustzcash.git"] [source."https://github.com/zcash/librustzcash.git"]
git = "https://github.com/zcash/librustzcash.git" git = "https://github.com/zcash/librustzcash.git"
rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
replace-with = "vendored-sources"
[source."https://github.com/zcash/orchard.git"]
git = "https://github.com/zcash/orchard.git"
rev = "f206b3f5d4e31bba75d03d9d03d5fa25825a9384"
replace-with = "vendored-sources"
[source."https://github.com/zkcrypto/group.git"]
git = "https://github.com/zkcrypto/group.git"
rev = "a7f3ceb2373e9fe536996f7b4d55c797f3e667f0"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source.vendored-sources] [source.vendored-sources]

84
Cargo.lock generated
View File

@ -19,10 +19,11 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aead" name = "aead"
version = "0.4.3" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [ dependencies = [
"crypto-common",
"generic-array", "generic-array",
] ]
@ -33,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"cipher", "cipher 0.3.0",
"cpufeatures", "cpufeatures",
"opaque-debug", "opaque-debug",
] ]
@ -218,7 +219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
dependencies = [ dependencies = [
"block-padding", "block-padding",
"cipher", "cipher 0.3.0",
] ]
[[package]] [[package]]
@ -293,25 +294,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chacha20" name = "chacha20"
version = "0.8.1" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"cipher", "cipher 0.4.3",
"cpufeatures", "cpufeatures",
"zeroize",
] ]
[[package]] [[package]]
name = "chacha20poly1305" name = "chacha20poly1305"
version = "0.9.0" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [ dependencies = [
"aead", "aead",
"chacha20", "chacha20",
"cipher", "cipher 0.4.3",
"poly1305", "poly1305",
"zeroize", "zeroize",
] ]
@ -325,6 +325,17 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "cipher"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [
"crypto-common",
"inout",
"zeroize",
]
[[package]] [[package]]
name = "clearscreen" name = "clearscreen"
version = "1.0.10" version = "1.0.10"
@ -411,6 +422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [ dependencies = [
"generic-array", "generic-array",
"rand_core 0.6.3",
"typenum", "typenum",
] ]
@ -539,7 +551,7 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]] [[package]]
name = "equihash" name = "equihash"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
"byteorder", "byteorder",
@ -548,7 +560,7 @@ dependencies = [
[[package]] [[package]]
name = "f4jumble" name = "f4jumble"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
] ]
@ -589,7 +601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd910db5f9ca4dc3116f8c46367825807aa2b942f72565f16b4be0b208a00a9e" checksum = "cd910db5f9ca4dc3116f8c46367825807aa2b942f72565f16b4be0b208a00a9e"
dependencies = [ dependencies = [
"block-modes", "block-modes",
"cipher", "cipher 0.3.0",
"libm", "libm",
"num-bigint", "num-bigint",
"num-integer", "num-integer",
@ -676,10 +688,8 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]] [[package]]
name = "group" name = "group"
version = "0.12.0" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zkcrypto/group.git?rev=a7f3ceb2373e9fe536996f7b4d55c797f3e667f0#a7f3ceb2373e9fe536996f7b4d55c797f3e667f0"
checksum = "7391856def869c1c81063a03457c676fbcd419709c3dfb33d8d319de484b154d"
dependencies = [ dependencies = [
"byteorder",
"ff", "ff",
"rand_core 0.6.3", "rand_core 0.6.3",
"subtle", "subtle",
@ -880,6 +890,15 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -1245,8 +1264,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "orchard" name = "orchard"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zcash/orchard.git?rev=f206b3f5d4e31bba75d03d9d03d5fa25825a9384#f206b3f5d4e31bba75d03d9d03d5fa25825a9384"
checksum = "7619db7f917afd9b1139044c595fab1b6166de2db62317794b5f5e34a2104ae1"
dependencies = [ dependencies = [
"aes", "aes",
"bitvec", "bitvec",
@ -1418,9 +1436,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "poly1305" name = "poly1305"
version = "0.7.2" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [ dependencies = [
"cpufeatures", "cpufeatures",
"opaque-debug", "opaque-debug",
@ -2102,11 +2120,11 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "universal-hash" name = "universal-hash"
version = "0.4.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [ dependencies = [
"generic-array", "crypto-common",
"subtle", "subtle",
] ]
@ -2308,7 +2326,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_address" name = "zcash_address"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"bech32", "bech32",
"bs58", "bs58",
@ -2319,7 +2337,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_encoding" name = "zcash_encoding"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"nonempty", "nonempty",
@ -2328,7 +2346,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_history" name = "zcash_history"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
"byteorder", "byteorder",
@ -2338,10 +2356,12 @@ dependencies = [
[[package]] [[package]]
name = "zcash_note_encryption" name = "zcash_note_encryption"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"chacha20", "chacha20",
"chacha20poly1305", "chacha20poly1305",
"cipher 0.4.3",
"group",
"rand_core 0.6.3", "rand_core 0.6.3",
"subtle", "subtle",
] ]
@ -2349,7 +2369,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_primitives" name = "zcash_primitives"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"aes", "aes",
"bip0039", "bip0039",
@ -2386,7 +2406,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_proofs" name = "zcash_proofs"
version = "0.7.1" version = "0.7.1"
source = "git+https://github.com/zcash/librustzcash.git?rev=abe452d8a5a3d3bce102c3445f9e321d68296d8f#abe452d8a5a3d3bce102c3445f9e321d68296d8f" source = "git+https://github.com/zcash/librustzcash.git?rev=f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec#f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec"
dependencies = [ dependencies = [
"bellman", "bellman",
"blake2b_simd", "blake2b_simd",
@ -2405,9 +2425,9 @@ dependencies = [
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.4.3" version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
dependencies = [ dependencies = [
"zeroize_derive", "zeroize_derive",
] ]

View File

@ -111,10 +111,12 @@ panic = 'abort'
codegen-units = 1 codegen-units = 1
[patch.crates-io] [patch.crates-io]
equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "abe452d8a5a3d3bce102c3445f9e321d68296d8f" } zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "f78c91fd0cc9ac3ee9e183b1140da8745fcc8fec" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "f206b3f5d4e31bba75d03d9d03d5fa25825a9384" }
group = { git = "https://github.com/zkcrypto/group.git", rev = "a7f3ceb2373e9fe536996f7b4d55c797f3e667f0" }

View File

@ -14,7 +14,10 @@ use zcash_note_encryption::{batch, BatchDomain, Domain, ShieldedOutput, ENC_CIPH
use zcash_primitives::{ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus, constants, consensus, constants,
sapling::{self, note_encryption::SaplingDomain}, sapling::{
note_encryption::{PreparedIncomingViewingKey, SaplingDomain},
SaplingIvk,
},
transaction::{ transaction::{
components::{sapling::GrothProofBytes, OutputDescription}, components::{sapling::GrothProofBytes, OutputDescription},
Transaction, TxId, Transaction, TxId,
@ -214,9 +217,9 @@ impl<P: consensus::Parameters> OutputDomain for SaplingDomain<P> {
} }
/// A decrypted note. /// A decrypted note.
struct DecryptedNote<D: Domain> { struct DecryptedNote<A, D: Domain> {
/// The incoming viewing key used to decrypt the note. /// The tag corresponding to the incoming viewing key used to decrypt the note.
ivk: D::IncomingViewingKey, ivk_tag: A,
/// The recipient of the note. /// The recipient of the note.
recipient: D::Recipient, recipient: D::Recipient,
/// The note! /// The note!
@ -225,8 +228,9 @@ struct DecryptedNote<D: Domain> {
memo: D::Memo, memo: D::Memo,
} }
impl<D: Domain> fmt::Debug for DecryptedNote<D> impl<A, D: Domain> fmt::Debug for DecryptedNote<A, D>
where where
A: fmt::Debug,
D::IncomingViewingKey: fmt::Debug, D::IncomingViewingKey: fmt::Debug,
D::Recipient: fmt::Debug, D::Recipient: fmt::Debug,
D::Note: fmt::Debug, D::Note: fmt::Debug,
@ -234,7 +238,7 @@ where
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DecryptedNote") f.debug_struct("DecryptedNote")
.field("ivk", &self.ivk) .field("ivk_tag", &self.ivk_tag)
.field("recipient", &self.recipient) .field("recipient", &self.recipient)
.field("note", &self.note) .field("note", &self.note)
.field("memo", &self.memo) .field("memo", &self.memo)
@ -250,12 +254,12 @@ struct OutputIndex<V> {
value: V, value: V,
} }
type OutputItem<D> = OutputIndex<DecryptedNote<D>>; type OutputItem<A, D> = OutputIndex<DecryptedNote<A, D>>;
/// The sender for the result of batch scanning a specific transaction output. /// The sender for the result of batch scanning a specific transaction output.
struct OutputReplier<D: Domain>(OutputIndex<channel::Sender<OutputItem<D>>>); struct OutputReplier<A, D: Domain>(OutputIndex<channel::Sender<OutputItem<A, D>>>);
impl<D: Domain> DynamicUsage for OutputReplier<D> { impl<A, D: Domain> DynamicUsage for OutputReplier<A, D> {
#[inline(always)] #[inline(always)]
fn dynamic_usage(&self) -> usize { fn dynamic_usage(&self) -> usize {
// We count the memory usage of items in the channel on the receiver side. // We count the memory usage of items in the channel on the receiver side.
@ -269,7 +273,8 @@ impl<D: Domain> DynamicUsage for OutputReplier<D> {
} }
/// A batch of outputs to trial decrypt. /// A batch of outputs to trial decrypt.
struct Batch<D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>> { struct Batch<A, D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>> {
tags: Vec<A>,
ivks: Vec<D::IncomingViewingKey>, ivks: Vec<D::IncomingViewingKey>,
/// We currently store outputs and repliers as parallel vectors, because /// We currently store outputs and repliers as parallel vectors, because
/// [`batch::try_note_decryption`] accepts a slice of domain/output pairs /// [`batch::try_note_decryption`] accepts a slice of domain/output pairs
@ -279,7 +284,7 @@ struct Batch<D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>> {
/// all be part of the same struct, which would also track the output index /// all be part of the same struct, which would also track the output index
/// (that is captured in the outer `OutputIndex` of each `OutputReplier`). /// (that is captured in the outer `OutputIndex` of each `OutputReplier`).
outputs: Vec<(D, Output)>, outputs: Vec<(D, Output)>,
repliers: Vec<OutputReplier<D>>, repliers: Vec<OutputReplier<A, D>>,
// Pointer to the parent `BatchRunner`'s heap usage tracker for running batches. // Pointer to the parent `BatchRunner`'s heap usage tracker for running batches.
running_usage: Arc<AtomicUsize>, running_usage: Arc<AtomicUsize>,
} }
@ -288,7 +293,7 @@ fn base_vec_usage<T>(c: &Vec<T>) -> usize {
c.capacity() * mem::size_of::<T>() c.capacity() * mem::size_of::<T>()
} }
impl<D, Output> DynamicUsage for Batch<D, Output> impl<A, D, Output> DynamicUsage for Batch<A, D, Output>
where where
D: BatchDomain, D: BatchDomain,
Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>,
@ -311,15 +316,21 @@ where
} }
} }
impl<D, Output> Batch<D, Output> impl<A, D, Output> Batch<A, D, Output>
where where
A: Clone,
D: OutputDomain, D: OutputDomain,
Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>,
D::IncomingViewingKey: Clone,
{ {
/// Constructs a new batch. /// Constructs a new batch.
fn new(ivks: Vec<D::IncomingViewingKey>, running_usage: Arc<AtomicUsize>) -> Self { fn new(
tags: Vec<A>,
ivks: Vec<D::IncomingViewingKey>,
running_usage: Arc<AtomicUsize>,
) -> Self {
assert_eq!(tags.len(), ivks.len());
Self { Self {
tags,
ivks, ivks,
outputs: vec![], outputs: vec![],
repliers: vec![], repliers: vec![],
@ -342,6 +353,7 @@ where
// Deconstruct self so we can consume the pieces individually. // Deconstruct self so we can consume the pieces individually.
let Self { let Self {
tags,
ivks, ivks,
outputs, outputs,
repliers, repliers,
@ -365,7 +377,7 @@ where
let result = OutputIndex { let result = OutputIndex {
output_index: replier.output_index, output_index: replier.output_index,
value: DecryptedNote { value: DecryptedNote {
ivk: ivks[ivk_idx].clone(), ivk_tag: tags[ivk_idx].clone(),
recipient, recipient,
note, note,
memo, memo,
@ -384,7 +396,9 @@ where
} }
} }
impl<D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE> + Clone> Batch<D, Output> { impl<A, D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE> + Clone>
Batch<A, D, Output>
{
/// Adds the given outputs to this batch. /// Adds the given outputs to this batch.
/// ///
/// `replier` will be called with the result of every output. /// `replier` will be called with the result of every output.
@ -392,7 +406,7 @@ impl<D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE> + Clone> Bat
&mut self, &mut self,
domain: impl Fn() -> D, domain: impl Fn() -> D,
outputs: &[Output], outputs: &[Output],
replier: channel::Sender<OutputItem<D>>, replier: channel::Sender<OutputItem<A, D>>,
) { ) {
self.outputs self.outputs
.extend(outputs.iter().cloned().map(|output| (domain(), output))); .extend(outputs.iter().cloned().map(|output| (domain(), output)));
@ -422,9 +436,9 @@ impl DynamicUsage for ResultKey {
} }
/// The receiver for the result of batch scanning a specific transaction. /// The receiver for the result of batch scanning a specific transaction.
struct BatchReceiver<D: Domain>(channel::Receiver<OutputItem<D>>); struct BatchReceiver<A, D: Domain>(channel::Receiver<OutputItem<A, D>>);
impl<D: Domain> DynamicUsage for BatchReceiver<D> { impl<A, D: Domain> DynamicUsage for BatchReceiver<A, D> {
fn dynamic_usage(&self) -> usize { fn dynamic_usage(&self) -> usize {
// We count the memory usage of items in the channel on the receiver side. // We count the memory usage of items in the channel on the receiver side.
let num_items = self.0.len(); let num_items = self.0.len();
@ -441,7 +455,7 @@ impl<D: Domain> DynamicUsage for BatchReceiver<D> {
// - Space for an item. // - Space for an item.
// - The state of the slot, stored as an AtomicUsize. // - The state of the slot, stored as an AtomicUsize.
const PTR_SIZE: usize = std::mem::size_of::<usize>(); const PTR_SIZE: usize = std::mem::size_of::<usize>();
let item_size = std::mem::size_of::<OutputItem<D>>(); let item_size = std::mem::size_of::<OutputItem<A, D>>();
const ATOMIC_USIZE_SIZE: usize = std::mem::size_of::<AtomicUsize>(); const ATOMIC_USIZE_SIZE: usize = std::mem::size_of::<AtomicUsize>();
let block_size = PTR_SIZE + ITEMS_PER_BLOCK * (item_size + ATOMIC_USIZE_SIZE); let block_size = PTR_SIZE + ITEMS_PER_BLOCK * (item_size + ATOMIC_USIZE_SIZE);
@ -455,16 +469,16 @@ impl<D: Domain> DynamicUsage for BatchReceiver<D> {
} }
/// Logic to run batches of trial decryptions on the global threadpool. /// Logic to run batches of trial decryptions on the global threadpool.
struct BatchRunner<D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>> { struct BatchRunner<A, D: BatchDomain, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>> {
// The batch currently being accumulated. // The batch currently being accumulated.
acc: Batch<D, Output>, acc: Batch<A, D, Output>,
// The dynamic memory usage of the running batches. // The dynamic memory usage of the running batches.
running_usage: Arc<AtomicUsize>, running_usage: Arc<AtomicUsize>,
// Receivers for the results of the running batches. // Receivers for the results of the running batches.
pending_results: HashMap<ResultKey, BatchReceiver<D>>, pending_results: HashMap<ResultKey, BatchReceiver<A, D>>,
} }
impl<D, Output> DynamicUsage for BatchRunner<D, Output> impl<A, D, Output> DynamicUsage for BatchRunner<A, D, Output>
where where
D: BatchDomain, D: BatchDomain,
Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>,
@ -493,27 +507,29 @@ where
} }
} }
impl<D, Output> BatchRunner<D, Output> impl<A, D, Output> BatchRunner<A, D, Output>
where where
A: Clone,
D: OutputDomain, D: OutputDomain,
Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>, Output: ShieldedOutput<D, ENC_CIPHERTEXT_SIZE>,
D::IncomingViewingKey: Clone,
{ {
/// Constructs a new batch runner for the given incoming viewing keys. /// Constructs a new batch runner for the given incoming viewing keys.
fn new(ivks: Vec<D::IncomingViewingKey>) -> Self { fn new(ivks: impl Iterator<Item = (A, D::IncomingViewingKey)>) -> Self {
let running_usage = Arc::new(AtomicUsize::new(0)); let running_usage = Arc::new(AtomicUsize::new(0));
let (tags, ivks) = ivks.unzip();
Self { Self {
acc: Batch::new(ivks, running_usage.clone()), acc: Batch::new(tags, ivks, running_usage.clone()),
running_usage, running_usage,
pending_results: HashMap::default(), pending_results: HashMap::default(),
} }
} }
} }
impl<D, Output> BatchRunner<D, Output> impl<A, D, Output> BatchRunner<A, D, Output>
where where
A: Clone + Send + 'static,
D: OutputDomain + Send + 'static, D: OutputDomain + Send + 'static,
D::IncomingViewingKey: Clone + Send, D::IncomingViewingKey: Clone + Send + 'static,
D::Memo: Send, D::Memo: Send,
D::Note: Send, D::Note: Send,
D::Recipient: Send, D::Recipient: Send,
@ -550,7 +566,11 @@ where
/// Subsequent calls to `Self::add_outputs` will be accumulated into a new batch. /// Subsequent calls to `Self::add_outputs` will be accumulated into a new batch.
fn flush(&mut self) { fn flush(&mut self) {
if !self.acc.is_empty() { if !self.acc.is_empty() {
let mut batch = Batch::new(self.acc.ivks.clone(), self.running_usage.clone()); let mut batch = Batch::new(
self.acc.tags.clone(),
self.acc.ivks.clone(),
self.running_usage.clone(),
);
mem::swap(&mut batch, &mut self.acc); mem::swap(&mut batch, &mut self.acc);
rayon::spawn_fifo(|| batch.run()); rayon::spawn_fifo(|| batch.run());
} }
@ -565,7 +585,7 @@ where
&mut self, &mut self,
block_tag: BlockHash, block_tag: BlockHash,
txid: TxId, txid: TxId,
) -> HashMap<(TxId, usize), DecryptedNote<D>> { ) -> HashMap<(TxId, usize), DecryptedNote<A, D>> {
self.pending_results self.pending_results
.remove(&ResultKey(block_tag, txid)) .remove(&ResultKey(block_tag, txid))
// We won't have a pending result if the transaction didn't have outputs of // We won't have a pending result if the transaction didn't have outputs of
@ -593,7 +613,8 @@ where
/// A batch scanner for the `zcashd` wallet. /// A batch scanner for the `zcashd` wallet.
struct BatchScanner { struct BatchScanner {
params: Network, params: Network,
sapling_runner: Option<BatchRunner<SaplingDomain<Network>, OutputDescription<GrothProofBytes>>>, sapling_runner:
Option<BatchRunner<[u8; 32], SaplingDomain<Network>, OutputDescription<GrothProofBytes>>>,
} }
impl DynamicUsage for BatchScanner { impl DynamicUsage for BatchScanner {
@ -613,15 +634,17 @@ fn init_batch_scanner(
let sapling_runner = if sapling_ivks.is_empty() { let sapling_runner = if sapling_ivks.is_empty() {
None None
} else { } else {
let ivks = sapling_ivks let ivks: Vec<(_, _)> = sapling_ivks
.iter() .iter()
.map(|ivk| { .map(|raw_ivk| {
let ivk: Option<sapling::SaplingIvk> = let ivk: Option<_> = jubjub::Fr::from_bytes(raw_ivk)
jubjub::Fr::from_bytes(ivk).map(sapling::SaplingIvk).into(); .map(|scalar_ivk| PreparedIncomingViewingKey::new(&SaplingIvk(scalar_ivk)))
ivk.ok_or("Invalid Sapling ivk passed to wallet::init_batch_scanner()") .into();
ivk.map(|prepared_ivk| (*raw_ivk, prepared_ivk))
.ok_or("Invalid Sapling ivk passed to wallet::init_batch_scanner()")
}) })
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
Some(BatchRunner::new(ivks)) Some(BatchRunner::new(ivks.into_iter()))
}; };
Ok(Box::new(BatchScanner { Ok(Box::new(BatchScanner {
@ -717,7 +740,7 @@ impl BatchScanner {
} }
struct BatchResult { struct BatchResult {
sapling: HashMap<(TxId, usize), DecryptedNote<SaplingDomain<Network>>>, sapling: HashMap<(TxId, usize), DecryptedNote<[u8; 32], SaplingDomain<Network>>>,
} }
impl BatchResult { impl BatchResult {
@ -728,7 +751,7 @@ impl BatchResult {
|((txid, output), decrypted_note)| ffi::SaplingDecryptionResult { |((txid, output), decrypted_note)| ffi::SaplingDecryptionResult {
txid: *txid.as_ref(), txid: *txid.as_ref(),
output: *output as u32, output: *output as u32,
ivk: decrypted_note.ivk.to_repr(), ivk: decrypted_note.ivk_tag,
diversifier: decrypted_note.recipient.diversifier().0, diversifier: decrypted_note.recipient.diversifier().0,
pk_d: decrypted_note.recipient.pk_d().to_bytes(), pk_d: decrypted_note.recipient.pk_d().to_bytes(),
}, },