mirror of https://github.com/zcash/orchard.git
Implement `Domain::batch_epk` for note decryption
Improves throughput of batched trial decryption by around 10%.
This commit is contained in:
parent
8c15cc25be
commit
8e13986101
23
src/keys.rs
23
src/keys.rs
|
@ -6,7 +6,7 @@ use std::mem;
|
||||||
use aes::Aes256;
|
use aes::Aes256;
|
||||||
use blake2b_simd::{Hash as Blake2bHash, Params};
|
use blake2b_simd::{Hash as Blake2bHash, Params};
|
||||||
use fpe::ff1::{BinaryNumeralString, FF1};
|
use fpe::ff1::{BinaryNumeralString, FF1};
|
||||||
use group::GroupEncoding;
|
use group::{prime::PrimeCurveAffine, Curve, GroupEncoding};
|
||||||
use halo2::arithmetic::FieldExt;
|
use halo2::arithmetic::FieldExt;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
@ -567,15 +567,34 @@ impl SharedSecret {
|
||||||
self.0.to_bytes()
|
self.0.to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Only for use in batched note encryption.
|
||||||
|
pub(crate) fn batch_to_affine(shared_secrets: &[Option<Self>]) -> Vec<pallas::Affine> {
|
||||||
|
let secrets: Vec<_> = shared_secrets
|
||||||
|
.iter()
|
||||||
|
.filter_map(|s| s.as_ref().map(|s| *(s.0)))
|
||||||
|
.collect();
|
||||||
|
let mut secrets_affine = vec![pallas::Affine::identity(); shared_secrets.len()];
|
||||||
|
group::Curve::batch_normalize(&secrets, &mut secrets_affine);
|
||||||
|
secrets_affine
|
||||||
|
}
|
||||||
|
|
||||||
/// Defined in [Zcash Protocol Spec § 5.4.5.6: Orchard Key Agreement][concreteorchardkdf].
|
/// Defined in [Zcash Protocol Spec § 5.4.5.6: Orchard Key Agreement][concreteorchardkdf].
|
||||||
///
|
///
|
||||||
/// [concreteorchardkdf]: https://zips.z.cash/protocol/nu5.pdf#concreteorchardkdf
|
/// [concreteorchardkdf]: https://zips.z.cash/protocol/nu5.pdf#concreteorchardkdf
|
||||||
pub(crate) fn kdf_orchard(self, ephemeral_key: &EphemeralKeyBytes) -> Blake2bHash {
|
pub(crate) fn kdf_orchard(self, ephemeral_key: &EphemeralKeyBytes) -> Blake2bHash {
|
||||||
|
Self::kdf_orchard_inner(self.0.to_affine(), ephemeral_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Only for direct use in batched note encryption.
|
||||||
|
pub(crate) fn kdf_orchard_inner(
|
||||||
|
secret: pallas::Affine,
|
||||||
|
ephemeral_key: &EphemeralKeyBytes,
|
||||||
|
) -> Blake2bHash {
|
||||||
Params::new()
|
Params::new()
|
||||||
.hash_length(32)
|
.hash_length(32)
|
||||||
.personal(KDF_ORCHARD_PERSONALIZATION)
|
.personal(KDF_ORCHARD_PERSONALIZATION)
|
||||||
.to_state()
|
.to_state()
|
||||||
.update(&self.0.to_bytes())
|
.update(&secret.to_bytes())
|
||||||
.update(&ephemeral_key.0)
|
.update(&ephemeral_key.0)
|
||||||
.finalize()
|
.finalize()
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,24 @@ impl Domain for OrchardDomain {
|
||||||
secret.kdf_orchard(ephemeral_key)
|
secret.kdf_orchard(ephemeral_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn batch_kdf<'a>(
|
||||||
|
items: impl Iterator<Item = (Option<Self::SharedSecret>, &'a EphemeralKeyBytes)>,
|
||||||
|
) -> Vec<Option<Self::SymmetricKey>> {
|
||||||
|
let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip();
|
||||||
|
|
||||||
|
let secrets_affine = SharedSecret::batch_to_affine(&shared_secrets);
|
||||||
|
|
||||||
|
let mut secrets_affine = secrets_affine.into_iter();
|
||||||
|
shared_secrets
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.and_then(|_| secrets_affine.next()))
|
||||||
|
.zip(ephemeral_keys.into_iter())
|
||||||
|
.map(|(secret, ephemeral_key)| {
|
||||||
|
secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn note_plaintext_bytes(
|
fn note_plaintext_bytes(
|
||||||
note: &Self::Note,
|
note: &Self::Note,
|
||||||
_: &Self::Recipient,
|
_: &Self::Recipient,
|
||||||
|
|
Loading…
Reference in New Issue