Merge pull request #329 from nuttycom/ivk_payment_addresses
Introduce SaplingIvk newtype & use IVKs where possible.
This commit is contained in:
commit
36e4b0d51a
|
@ -292,6 +292,7 @@ where
|
|||
|
||||
let txs: Vec<WalletTx> = {
|
||||
let mut witness_refs: Vec<_> = witnesses.iter_mut().map(|w| &mut w.1).collect();
|
||||
|
||||
scan_block(
|
||||
params,
|
||||
block,
|
||||
|
|
|
@ -7,7 +7,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::try_sapling_compact_note_decryption,
|
||||
primitives::Nullifier,
|
||||
primitives::{Nullifier, SaplingIvk},
|
||||
sapling::Node,
|
||||
transaction::TxId,
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ fn scan_output<P: consensus::Parameters>(
|
|||
params: &P,
|
||||
height: BlockHeight,
|
||||
(index, output): (usize, CompactOutput),
|
||||
ivks: &[(AccountId, jubjub::Fr)],
|
||||
ivks: &[(AccountId, SaplingIvk)],
|
||||
spent_from_accounts: &HashSet<AccountId>,
|
||||
tree: &mut CommitmentTree<Node>,
|
||||
existing_witnesses: &mut [&mut IncrementalWitness<Node>],
|
||||
|
@ -53,7 +53,7 @@ fn scan_output<P: consensus::Parameters>(
|
|||
|
||||
for (account, ivk) in ivks.iter() {
|
||||
let (note, to) =
|
||||
match try_sapling_compact_note_decryption(params, height, ivk, &epk, &cmu, &ct) {
|
||||
match try_sapling_compact_note_decryption(params, height, &ivk, &epk, &cmu, &ct) {
|
||||
Some(ret) => ret,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -90,7 +90,7 @@ fn scan_output<P: consensus::Parameters>(
|
|||
pub fn scan_block<P: consensus::Parameters>(
|
||||
params: &P,
|
||||
block: CompactBlock,
|
||||
ivks: &[(AccountId, jubjub::Fr)],
|
||||
ivks: &[(AccountId, SaplingIvk)],
|
||||
nullifiers: &[(AccountId, Nullifier)],
|
||||
tree: &mut CommitmentTree<Node>,
|
||||
existing_witnesses: &mut [&mut IncrementalWitness<Node>],
|
||||
|
@ -163,7 +163,7 @@ pub fn scan_block<P: consensus::Parameters>(
|
|||
params,
|
||||
block_height,
|
||||
to_scan,
|
||||
&ivks,
|
||||
ivks,
|
||||
&spent_from_accounts,
|
||||
tree,
|
||||
existing_witnesses,
|
||||
|
|
|
@ -4,7 +4,7 @@ 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},
|
||||
primitives::{Diversifier, PaymentAddress, SaplingIvk, ValueCommitment},
|
||||
transaction::components::{OutputDescription, GROTH_PROOF_SIZE},
|
||||
util::generate_random_rseed,
|
||||
};
|
||||
|
@ -13,13 +13,13 @@ 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);
|
||||
let valid_ivk = SaplingIvk(jubjub::Fr::random(&mut rng));
|
||||
let invalid_ivk = SaplingIvk(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 pk_d = diversifier.g_d().unwrap() * valid_ivk.0;
|
||||
let pa = PaymentAddress::from_parts(diversifier, pk_d).unwrap();
|
||||
|
||||
let rseed = generate_random_rseed(&TEST_NETWORK, height, &mut rng);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::{
|
||||
consensus::{self, BlockHeight, NetworkUpgrade::Canopy, ZIP212_GRACE_PERIOD},
|
||||
primitives::{Diversifier, Note, PaymentAddress, Rseed},
|
||||
primitives::{Diversifier, Note, PaymentAddress, Rseed, SaplingIvk},
|
||||
};
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
@ -375,7 +375,7 @@ impl<R: RngCore> SaplingNoteEncryption<R> {
|
|||
fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
ivk: &jubjub::Fr,
|
||||
ivk: &SaplingIvk,
|
||||
epk: &jubjub::ExtendedPoint,
|
||||
cmu: &bls12_381::Scalar,
|
||||
plaintext: &[u8],
|
||||
|
@ -402,7 +402,7 @@ fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
|||
};
|
||||
|
||||
let diversifier = Diversifier(d);
|
||||
let pk_d = diversifier.g_d()? * ivk;
|
||||
let pk_d = diversifier.g_d()? * ivk.0;
|
||||
|
||||
let to = PaymentAddress::from_parts(diversifier, pk_d)?;
|
||||
let note = to.create_note(v, rseed).unwrap();
|
||||
|
@ -458,14 +458,14 @@ pub fn plaintext_version_is_valid<P: consensus::Parameters>(
|
|||
pub fn try_sapling_note_decryption<P: consensus::Parameters>(
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
ivk: &jubjub::Fr,
|
||||
ivk: &SaplingIvk,
|
||||
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);
|
||||
let shared_secret = sapling_ka_agree(&ivk.0, &epk);
|
||||
let key = kdf_sapling(shared_secret, &epk);
|
||||
|
||||
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
|
||||
|
@ -502,14 +502,14 @@ pub fn try_sapling_note_decryption<P: consensus::Parameters>(
|
|||
pub fn try_sapling_compact_note_decryption<P: consensus::Parameters>(
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
ivk: &jubjub::Fr,
|
||||
ivk: &SaplingIvk,
|
||||
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);
|
||||
let shared_secret = sapling_ka_agree(&ivk.0, epk);
|
||||
let key = kdf_sapling(shared_secret, &epk);
|
||||
|
||||
// Start from block 1 to skip over Poly1305 keying output
|
||||
|
@ -683,7 +683,7 @@ mod tests {
|
|||
Parameters, TEST_NETWORK, ZIP212_GRACE_PERIOD,
|
||||
},
|
||||
keys::OutgoingViewingKey,
|
||||
primitives::{Diversifier, PaymentAddress, Rseed, ValueCommitment},
|
||||
primitives::{Diversifier, PaymentAddress, Rseed, SaplingIvk, ValueCommitment},
|
||||
util::generate_random_rseed,
|
||||
};
|
||||
|
||||
|
@ -809,17 +809,17 @@ mod tests {
|
|||
) -> (
|
||||
OutgoingViewingKey,
|
||||
OutgoingCipherKey,
|
||||
jubjub::Fr,
|
||||
SaplingIvk,
|
||||
jubjub::ExtendedPoint,
|
||||
bls12_381::Scalar,
|
||||
jubjub::ExtendedPoint,
|
||||
[u8; ENC_CIPHERTEXT_SIZE],
|
||||
[u8; OUT_CIPHERTEXT_SIZE],
|
||||
) {
|
||||
let ivk = jubjub::Fr::random(&mut rng);
|
||||
let ivk = SaplingIvk(jubjub::Fr::random(&mut rng));
|
||||
|
||||
let (ovk, ock, ivk, cv, cmu, epk, enc_ciphertext, out_ciphertext) =
|
||||
random_enc_ciphertext_with(height, ivk, rng);
|
||||
let (ovk, ock, cv, cmu, epk, enc_ciphertext, out_ciphertext) =
|
||||
random_enc_ciphertext_with(height, &ivk, rng);
|
||||
|
||||
assert!(try_sapling_note_decryption(
|
||||
&TEST_NETWORK,
|
||||
|
@ -869,12 +869,11 @@ mod tests {
|
|||
|
||||
fn random_enc_ciphertext_with<R: RngCore + CryptoRng>(
|
||||
height: BlockHeight,
|
||||
ivk: jubjub::Fr,
|
||||
ivk: &SaplingIvk,
|
||||
mut rng: &mut R,
|
||||
) -> (
|
||||
OutgoingViewingKey,
|
||||
OutgoingCipherKey,
|
||||
jubjub::Fr,
|
||||
jubjub::ExtendedPoint,
|
||||
bls12_381::Scalar,
|
||||
jubjub::ExtendedPoint,
|
||||
|
@ -882,7 +881,7 @@ mod tests {
|
|||
[u8; OUT_CIPHERTEXT_SIZE],
|
||||
) {
|
||||
let diversifier = Diversifier([0; 11]);
|
||||
let pk_d = diversifier.g_d().unwrap() * ivk;
|
||||
let pk_d = diversifier.g_d().unwrap() * ivk.0;
|
||||
let pa = PaymentAddress::from_parts_unchecked(diversifier, pk_d);
|
||||
|
||||
// Construct the value commitment for the proof instance
|
||||
|
@ -905,7 +904,7 @@ mod tests {
|
|||
let out_ciphertext = ne.encrypt_outgoing_plaintext(&cv, &cmu);
|
||||
let ock = prf_ock(&ovk, &cv, &cmu, &epk);
|
||||
|
||||
(ovk, ock, ivk, cv, cmu, epk, enc_ciphertext, out_ciphertext)
|
||||
(ovk, ock, cv, cmu, epk, enc_ciphertext, out_ciphertext)
|
||||
}
|
||||
|
||||
fn reencrypt_enc_ciphertext(
|
||||
|
@ -1006,7 +1005,7 @@ mod tests {
|
|||
try_sapling_note_decryption(
|
||||
&TEST_NETWORK,
|
||||
height,
|
||||
&jubjub::Fr::random(&mut rng),
|
||||
&SaplingIvk(jubjub::Fr::random(&mut rng)),
|
||||
&epk,
|
||||
&cmu,
|
||||
&enc_ciphertext
|
||||
|
@ -1217,7 +1216,7 @@ mod tests {
|
|||
try_sapling_compact_note_decryption(
|
||||
&TEST_NETWORK,
|
||||
height,
|
||||
&jubjub::Fr::random(&mut rng),
|
||||
&SaplingIvk(jubjub::Fr::random(&mut rng)),
|
||||
&epk,
|
||||
&cmu,
|
||||
&enc_ciphertext[..COMPACT_NOTE_SIZE]
|
||||
|
@ -1792,9 +1791,9 @@ mod tests {
|
|||
];
|
||||
|
||||
for &height in heights.iter() {
|
||||
let ivk = jubjub::Fr::zero();
|
||||
let (ovk, ock, _, cv, cmu, epk, enc_ciphertext, out_ciphertext) =
|
||||
random_enc_ciphertext_with(height, ivk, &mut rng);
|
||||
let ivk = SaplingIvk(jubjub::Fr::zero());
|
||||
let (ovk, ock, cv, cmu, epk, enc_ciphertext, out_ciphertext) =
|
||||
random_enc_ciphertext_with(height, &ivk, &mut rng);
|
||||
|
||||
assert_eq!(
|
||||
try_sapling_output_recovery(
|
||||
|
@ -1853,7 +1852,7 @@ mod tests {
|
|||
// Load the test vector components
|
||||
//
|
||||
|
||||
let ivk = read_jubjub_scalar!(tv.ivk);
|
||||
let ivk = SaplingIvk(read_jubjub_scalar!(tv.ivk));
|
||||
let pk_d = read_point!(tv.default_pk_d).into_subgroup().unwrap();
|
||||
let rcm = read_jubjub_scalar!(tv.rcm);
|
||||
let cv = read_point!(tv.cv);
|
||||
|
|
|
@ -59,7 +59,7 @@ impl ViewingKey {
|
|||
self.ak + constants::SPENDING_KEY_GENERATOR * ar
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> jubjub::Fr {
|
||||
pub fn ivk(&self) -> SaplingIvk {
|
||||
let mut h = [0; 32];
|
||||
h.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
|
@ -75,16 +75,28 @@ impl ViewingKey {
|
|||
// Drop the most significant five bits, so it can be interpreted as a scalar.
|
||||
h[31] &= 0b0000_0111;
|
||||
|
||||
jubjub::Fr::from_repr(h).expect("should be a valid scalar")
|
||||
SaplingIvk(jubjub::Fr::from_repr(h).expect("should be a valid scalar"))
|
||||
}
|
||||
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
self.ivk().to_payment_address(diversifier)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SaplingIvk(pub jubjub::Fr);
|
||||
|
||||
impl SaplingIvk {
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
diversifier.g_d().and_then(|g_d| {
|
||||
let pk_d = g_d * self.ivk();
|
||||
let pk_d = g_d * self.0;
|
||||
|
||||
PaymentAddress::from_parts(diversifier, pk_d)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_repr(&self) -> [u8; 32] {
|
||||
self.0.to_repr()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
|
Loading…
Reference in New Issue