Merge remote-tracking branch 'upstream/master' into zip-tzes

Fix benchmark build issues.
This commit is contained in:
Kris Nuttycombe 2020-09-21 16:41:40 -06:00
commit a0a36eddfd
9 changed files with 124 additions and 43 deletions

View File

@ -1,4 +1,3 @@
use group::cofactor::CofactorGroup;
use zcash_primitives::{
consensus::{self, BlockHeight},
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery, Memo},
@ -45,18 +44,12 @@ pub fn decrypt_transaction<P: consensus::Parameters>(
.collect();
for (index, output) in tx.shielded_outputs.iter().enumerate() {
let epk = output.ephemeral_key.into_subgroup();
if epk.is_none().into() {
continue;
}
let epk = epk.unwrap();
for (account, (ivk, ovk)) in vks.iter().enumerate() {
let ((note, to, memo), outgoing) = match try_sapling_note_decryption(
params,
height,
ivk,
&epk,
&output.ephemeral_key,
&output.cmu,
&output.enc_ciphertext,
) {
@ -67,7 +60,7 @@ pub fn decrypt_transaction<P: consensus::Parameters>(
ovk,
&output.cv,
&output.cmu,
&epk,
&output.ephemeral_key,
&output.enc_ciphertext,
&output.out_ciphertext,
) {

View File

@ -86,8 +86,8 @@ impl compact_formats::CompactOutput {
/// A convenience method that parses [`CompactOutput.epk`].
///
/// [`CompactOutput.epk`]: #structfield.epk
pub fn epk(&self) -> Result<jubjub::SubgroupPoint, ()> {
let p = jubjub::SubgroupPoint::from_bytes(&self.epk[..].try_into().map_err(|_| ())?);
pub fn epk(&self) -> Result<jubjub::ExtendedPoint, ()> {
let p = jubjub::ExtendedPoint::from_bytes(&self.epk[..].try_into().map_err(|_| ())?);
if p.is_some().into() {
Ok(p.unwrap())
} else {

View File

@ -35,7 +35,7 @@ pub struct WalletShieldedSpend {
pub struct WalletShieldedOutput {
pub index: usize,
pub cmu: bls12_381::Scalar,
pub epk: jubjub::SubgroupPoint,
pub epk: jubjub::ExtendedPoint,
pub account: usize,
pub note: Note,
pub to: PaymentAddress,

View File

@ -370,7 +370,6 @@ pub fn create_to_address<DB: AsRef<Path>, P: consensus::Parameters>(
#[cfg(test)]
mod tests {
use group::cofactor::CofactorGroup;
use rusqlite::Connection;
use tempfile::NamedTempFile;
@ -832,7 +831,7 @@ mod tests {
&extfvk.fvk.ovk,
&output.cv,
&output.cmu,
&output.ephemeral_key.into_subgroup().unwrap(),
&output.ephemeral_key,
&output.enc_ciphertext,
&output.out_ciphertext,
)

View File

@ -46,6 +46,10 @@ proptest = "0.10.1"
[features]
transparent-inputs = ["ripemd160", "secp256k1"]
[[bench]]
name = "note_decryption"
harness = false
[[bench]]
name = "pedersen_hash"
harness = false

View File

@ -0,0 +1,84 @@
use criterion::{criterion_group, criterion_main, Criterion};
use ff::Field;
use rand_core::OsRng;
use zcash_primitives::{
consensus::{NetworkUpgrade::Canopy, Parameters, TEST_NETWORK},
note_encryption::{try_sapling_note_decryption, Memo, SaplingNoteEncryption},
primitives::{Diversifier, PaymentAddress, ValueCommitment},
transaction::components::{OutputDescription, GROTH_PROOF_SIZE},
util::generate_random_rseed,
};
fn bench_note_decryption(c: &mut Criterion) {
let mut rng = OsRng;
let height = TEST_NETWORK.activation_height(Canopy).unwrap();
let valid_ivk = jubjub::Fr::random(&mut rng);
let invalid_ivk = jubjub::Fr::random(&mut rng);
// Construct a fake Sapling output as if we had just deserialized a transaction.
let output = {
let diversifier = Diversifier([0; 11]);
let pk_d = diversifier.g_d().unwrap() * valid_ivk;
let pa = PaymentAddress::from_parts(diversifier, pk_d).unwrap();
let rseed = generate_random_rseed(&TEST_NETWORK, height, &mut rng);
// Construct the value commitment for the proof instance
let value = 100;
let value_commitment = ValueCommitment {
value,
randomness: jubjub::Fr::random(&mut rng),
};
let cv = value_commitment.commitment().into();
let note = pa.create_note(value, rseed).unwrap();
let cmu = note.cmu();
let mut ne = SaplingNoteEncryption::new(None, note, pa, Memo::default(), &mut rng);
let ephemeral_key = ne.epk().clone().into();
let enc_ciphertext = ne.encrypt_note_plaintext();
let out_ciphertext = ne.encrypt_outgoing_plaintext(&cv, &cmu);
OutputDescription {
cv,
cmu,
ephemeral_key,
enc_ciphertext,
out_ciphertext,
zkproof: [0; GROTH_PROOF_SIZE],
}
};
let mut group = c.benchmark_group("Sapling note decryption");
group.bench_function("valid", |b| {
b.iter(|| {
try_sapling_note_decryption(
&TEST_NETWORK,
height,
&valid_ivk,
&output.ephemeral_key,
&output.cmu,
&output.enc_ciphertext,
)
.unwrap()
})
});
group.bench_function("invalid", |b| {
b.iter(|| {
try_sapling_note_decryption(
&TEST_NETWORK,
height,
&invalid_ivk,
&output.ephemeral_key,
&output.cmu,
&output.enc_ciphertext,
)
})
});
}
criterion_group!(benches, bench_note_decryption);
criterion_main!(benches);

View File

@ -142,7 +142,7 @@ pub fn sapling_ka_agree(esk: &jubjub::Fr, pk_d: &jubjub::ExtendedPoint) -> jubju
/// Sapling KDF for note encryption.
///
/// Implements section 5.4.4.4 of the Zcash Protocol Specification.
fn kdf_sapling(dhsecret: jubjub::SubgroupPoint, epk: &jubjub::SubgroupPoint) -> Blake2bHash {
fn kdf_sapling(dhsecret: jubjub::SubgroupPoint, epk: &jubjub::ExtendedPoint) -> Blake2bHash {
Blake2bParams::new()
.hash_length(32)
.personal(KDF_SAPLING_PERSONALIZATION)
@ -174,7 +174,7 @@ pub fn prf_ock(
ovk: &OutgoingViewingKey,
cv: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
) -> OutgoingCipherKey {
OutgoingCipherKey(
Blake2bParams::new()
@ -287,7 +287,7 @@ impl<R: RngCore + CryptoRng> SaplingNoteEncryption<R> {
/// Generates `encCiphertext` for this note.
pub fn encrypt_note_plaintext(&self) -> [u8; ENC_CIPHERTEXT_SIZE] {
let shared_secret = sapling_ka_agree(&self.esk, self.to.pk_d().into());
let key = kdf_sapling(shared_secret, &self.epk);
let key = kdf_sapling(shared_secret, &self.epk.into());
// Note plaintext encoding is defined in section 5.5 of the Zcash Protocol
// Specification.
@ -328,7 +328,7 @@ impl<R: RngCore + CryptoRng> SaplingNoteEncryption<R> {
cmu: &bls12_381::Scalar,
) -> [u8; OUT_CIPHERTEXT_SIZE] {
let (ock, input) = if let Some(ovk) = &self.ovk {
let ock = prf_ock(ovk, &cv, &cmu, &self.epk);
let ock = prf_ock(ovk, &cv, &cmu, &self.epk.into());
let mut input = [0u8; OUT_PLAINTEXT_SIZE];
input[0..32].copy_from_slice(&self.note.pk_d.to_bytes());
@ -362,7 +362,7 @@ fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
params: &P,
height: BlockHeight,
ivk: &jubjub::Fr,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
plaintext: &[u8],
) -> Option<(Note, PaymentAddress)> {
@ -399,7 +399,8 @@ fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
}
if let Some(derived_esk) = note.derive_esk() {
if (note.g_d * derived_esk) != *epk {
// This enforces that epk is a jubjub::SubgroupPoint.
if (note.g_d * derived_esk).to_bytes() != epk.to_bytes() {
return None;
}
}
@ -442,13 +443,13 @@ pub fn try_sapling_note_decryption<P: consensus::Parameters>(
params: &P,
height: BlockHeight,
ivk: &jubjub::Fr,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
enc_ciphertext: &[u8],
) -> Option<(Note, PaymentAddress, Memo)> {
assert_eq!(enc_ciphertext.len(), ENC_CIPHERTEXT_SIZE);
let shared_secret = sapling_ka_agree(ivk, epk.into());
let shared_secret = sapling_ka_agree(ivk, &epk);
let key = kdf_sapling(shared_secret, &epk);
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
@ -486,13 +487,13 @@ pub fn try_sapling_compact_note_decryption<P: consensus::Parameters>(
params: &P,
height: BlockHeight,
ivk: &jubjub::Fr,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
enc_ciphertext: &[u8],
) -> Option<(Note, PaymentAddress)> {
assert_eq!(enc_ciphertext.len(), COMPACT_NOTE_SIZE);
let shared_secret = sapling_ka_agree(ivk, epk.into());
let shared_secret = sapling_ka_agree(ivk, epk);
let key = kdf_sapling(shared_secret, &epk);
// Start from block 1 to skip over Poly1305 keying output
@ -516,7 +517,7 @@ pub fn try_sapling_output_recovery_with_ock<P: consensus::Parameters>(
height: BlockHeight,
ock: &OutgoingCipherKey,
cmu: &bls12_381::Scalar,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
enc_ciphertext: &[u8],
out_ciphertext: &[u8],
) -> Option<(Note, PaymentAddress, Memo)> {
@ -589,7 +590,7 @@ pub fn try_sapling_output_recovery_with_ock<P: consensus::Parameters>(
memo.copy_from_slice(&plaintext[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]);
let diversifier = Diversifier(d);
if diversifier.g_d()? * esk != *epk {
if (diversifier.g_d()? * esk).to_bytes() != epk.to_bytes() {
// Published epk doesn't match calculated epk
return None;
}
@ -624,7 +625,7 @@ pub fn try_sapling_output_recovery<P: consensus::Parameters>(
ovk: &OutgoingViewingKey,
cv: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
enc_ciphertext: &[u8],
out_ciphertext: &[u8],
) -> Option<(Note, PaymentAddress, Memo)> {
@ -794,7 +795,7 @@ mod tests {
jubjub::Fr,
jubjub::ExtendedPoint,
bls12_381::Scalar,
jubjub::SubgroupPoint,
jubjub::ExtendedPoint,
[u8; ENC_CIPHERTEXT_SIZE],
[u8; OUT_CIPHERTEXT_SIZE],
) {
@ -859,7 +860,7 @@ mod tests {
jubjub::Fr,
jubjub::ExtendedPoint,
bls12_381::Scalar,
jubjub::SubgroupPoint,
jubjub::ExtendedPoint,
[u8; ENC_CIPHERTEXT_SIZE],
[u8; OUT_CIPHERTEXT_SIZE],
) {
@ -882,7 +883,7 @@ mod tests {
let ovk = OutgoingViewingKey([0; 32]);
let mut ne = SaplingNoteEncryption::new(Some(ovk), note, pa, Memo([0; 512]), &mut rng);
let epk = ne.epk().clone();
let epk = ne.epk().clone().into();
let enc_ciphertext = ne.encrypt_note_plaintext();
let out_ciphertext = ne.encrypt_outgoing_plaintext(&cv, &cmu);
let ock = prf_ock(&ovk, &cv, &cmu, &epk);
@ -894,7 +895,7 @@ mod tests {
ovk: &OutgoingViewingKey,
cv: &jubjub::ExtendedPoint,
cmu: &bls12_381::Scalar,
epk: &jubjub::SubgroupPoint,
epk: &jubjub::ExtendedPoint,
enc_ciphertext: &mut [u8; ENC_CIPHERTEXT_SIZE],
out_ciphertext: &[u8; OUT_CIPHERTEXT_SIZE],
modify_plaintext: impl Fn(&mut [u8; NOTE_PLAINTEXT_SIZE]),
@ -1014,7 +1015,7 @@ mod tests {
&TEST_NETWORK,
height,
&ivk,
&jubjub::SubgroupPoint::random(&mut rng),
&jubjub::ExtendedPoint::random(&mut rng),
&cmu,
&enc_ciphertext
),
@ -1225,7 +1226,7 @@ mod tests {
&TEST_NETWORK,
height,
&ivk,
&jubjub::SubgroupPoint::random(&mut rng),
&jubjub::ExtendedPoint::random(&mut rng),
&cmu,
&enc_ciphertext[..COMPACT_NOTE_SIZE]
),
@ -1511,7 +1512,7 @@ mod tests {
&ovk,
&cv,
&cmu,
&jubjub::SubgroupPoint::random(&mut rng),
&jubjub::ExtendedPoint::random(&mut rng),
&enc_ciphertext,
&out_ciphertext
),
@ -1524,7 +1525,7 @@ mod tests {
height,
&ock,
&cmu,
&jubjub::SubgroupPoint::random(&mut rng),
&jubjub::ExtendedPoint::random(&mut rng),
&enc_ciphertext,
&out_ciphertext
),
@ -1841,7 +1842,7 @@ mod tests {
let cv = read_point!(tv.cv);
let cmu = read_bls12_381_scalar!(tv.cmu);
let esk = read_jubjub_scalar!(tv.esk);
let epk = read_point!(tv.epk).into_subgroup().unwrap();
let epk = read_point!(tv.epk);
//
// Test the individual components
@ -1915,7 +1916,7 @@ mod tests {
let mut ne = SaplingNoteEncryption::new(Some(ovk), note, to, Memo(tv.memo), OsRng);
// Swap in the ephemeral keypair from the test vectors
ne.esk = esk;
ne.epk = epk;
ne.epk = epk.into_subgroup().unwrap();
assert_eq!(&ne.encrypt_note_plaintext()[..], &tv.c_enc[..]);
assert_eq!(&ne.encrypt_outgoing_plaintext(&cv, &cmu)[..], &tv.c_out[..]);

View File

@ -8,7 +8,7 @@ use lazy_static::lazy_static;
use zcash_primitives::constants::{PEDERSEN_HASH_CHUNKS_PER_GENERATOR, PEDERSEN_HASH_GENERATORS};
/// The `d` constant of the twisted Edwards curve.
pub const EDWARDS_D: Scalar = Scalar::from_raw([
pub(crate) const EDWARDS_D: Scalar = Scalar::from_raw([
0x0106_5fd6_d634_3eb1,
0x292d_7f6d_3757_9d26,
0xf5fd_9207_e6bd_7fd4,
@ -16,7 +16,7 @@ pub const EDWARDS_D: Scalar = Scalar::from_raw([
]);
/// The `A` constant of the birationally equivalent Montgomery curve.
pub const MONTGOMERY_A: Scalar = Scalar::from_raw([
pub(crate) const MONTGOMERY_A: Scalar = Scalar::from_raw([
0x0000_0000_0000_a002,
0x0000_0000_0000_0000,
0x0000_0000_0000_0000,
@ -24,7 +24,7 @@ pub const MONTGOMERY_A: Scalar = Scalar::from_raw([
]);
/// The scaling factor used for conversion to and from the Montgomery form.
pub const MONTGOMERY_SCALE: Scalar = Scalar::from_raw([
pub(crate) const MONTGOMERY_SCALE: Scalar = Scalar::from_raw([
0x8f45_35f7_cf82_b8d9,
0xce40_6970_3da8_8abd,
0x31de_341e_77d7_64e5,
@ -62,13 +62,13 @@ lazy_static! {
/// The pre-computed window tables `[-4, 3, 2, 1, 1, 2, 3, 4]` of different magnitudes
/// of the Pedersen hash segment generators.
pub static ref PEDERSEN_CIRCUIT_GENERATORS: Vec<Vec<Vec<(Scalar, Scalar)>>> =
pub(crate) static ref PEDERSEN_CIRCUIT_GENERATORS: Vec<Vec<Vec<(Scalar, Scalar)>>> =
generate_pedersen_circuit_generators();
}
/// Creates the 3-bit window table `[0, 1, ..., 8]` for different magnitudes of a fixed
/// generator.
fn generate_circuit_generator(mut gen: jubjub::SubgroupPoint) -> FixedGeneratorOwned {
pub fn generate_circuit_generator(mut gen: jubjub::SubgroupPoint) -> FixedGeneratorOwned {
let mut windows = vec![];
for _ in 0..FIXED_BASE_CHUNKS_PER_GENERATOR {

View File

@ -19,7 +19,7 @@ use directories::BaseDirs;
use std::path::PathBuf;
pub mod circuit;
mod constants;
pub mod constants;
mod hashreader;
pub mod sapling;
pub mod sprout;