Pass height to methods which encrypt or decrypt Sapling outputs
This commit is contained in:
parent
71d31abad6
commit
b537f0f712
|
@ -1,5 +1,6 @@
|
|||
use pairing::bls12_381::Bls12;
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery, Memo},
|
||||
primitives::{Note, PaymentAddress},
|
||||
transaction::Transaction,
|
||||
|
@ -30,7 +31,8 @@ pub struct DecryptedOutput {
|
|||
|
||||
/// Scans a [`Transaction`] for any information that can be decrypted by the set of
|
||||
/// [`ExtendedFullViewingKey`]s.
|
||||
pub fn decrypt_transaction(
|
||||
pub fn decrypt_transaction<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
tx: &Transaction,
|
||||
extfvks: &[ExtendedFullViewingKey],
|
||||
) -> Vec<DecryptedOutput> {
|
||||
|
@ -49,10 +51,18 @@ pub fn decrypt_transaction(
|
|||
};
|
||||
|
||||
for (account, (ivk, ovk)) in vks.iter().enumerate() {
|
||||
let ((note, to, memo), outgoing) =
|
||||
match try_sapling_note_decryption(ivk, &epk, &output.cmu, &output.enc_ciphertext) {
|
||||
let ((note, to, memo), outgoing) = match try_sapling_note_decryption(
|
||||
parameters,
|
||||
tx.expiry_height,
|
||||
ivk,
|
||||
&epk,
|
||||
&output.cmu,
|
||||
&output.enc_ciphertext,
|
||||
) {
|
||||
Some(ret) => (ret, false),
|
||||
None => match try_sapling_output_recovery(
|
||||
parameters,
|
||||
tx.expiry_height,
|
||||
ovk,
|
||||
&output.cv,
|
||||
&output.cmu,
|
||||
|
|
|
@ -4,6 +4,7 @@ use ff::PrimeField;
|
|||
use std::collections::HashSet;
|
||||
use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
jubjub::fs::Fs,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::try_sapling_compact_note_decryption,
|
||||
|
@ -22,7 +23,9 @@ use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx};
|
|||
///
|
||||
/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are incremented
|
||||
/// with this output's commitment.
|
||||
fn scan_output(
|
||||
fn scan_output<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
height: u32,
|
||||
(index, output): (usize, CompactOutput),
|
||||
ivks: &[Fs],
|
||||
spent_from_accounts: &HashSet<usize>,
|
||||
|
@ -49,7 +52,8 @@ fn scan_output(
|
|||
tree.append(node).unwrap();
|
||||
|
||||
for (account, ivk) in ivks.iter().enumerate() {
|
||||
let (note, to) = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) {
|
||||
let (note, to) =
|
||||
match try_sapling_compact_note_decryption(parameters, height, ivk, &epk, &cmu, &ct) {
|
||||
Some(ret) => ret,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -83,7 +87,8 @@ fn scan_output(
|
|||
///
|
||||
/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are
|
||||
/// incremented appropriately.
|
||||
pub fn scan_block(
|
||||
pub fn scan_block<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
block: CompactBlock,
|
||||
extfvks: &[ExtendedFullViewingKey],
|
||||
nullifiers: &[(&[u8], usize)],
|
||||
|
@ -151,6 +156,8 @@ pub fn scan_block(
|
|||
.collect();
|
||||
|
||||
if let Some(output) = scan_output(
|
||||
parameters,
|
||||
block.height as u32,
|
||||
to_scan,
|
||||
&ivks,
|
||||
&spent_from_accounts,
|
||||
|
@ -187,6 +194,7 @@ mod tests {
|
|||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
jubjub::{fs::Fs, FixedGenerators, JubjubParams, ToUniform},
|
||||
merkle_tree::CommitmentTree,
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
|
@ -318,7 +326,14 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 2);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
let txs = scan_block(
|
||||
&consensus::MainNetwork,
|
||||
cb,
|
||||
&[extfvk],
|
||||
&[],
|
||||
&mut tree,
|
||||
&mut [],
|
||||
);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
@ -350,7 +365,14 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 3);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
let txs = scan_block(
|
||||
&consensus::MainNetwork,
|
||||
cb,
|
||||
&[extfvk],
|
||||
&[],
|
||||
&mut tree,
|
||||
&mut [],
|
||||
);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
@ -378,7 +400,14 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 2);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[], &[(&nf, account)], &mut tree, &mut []);
|
||||
let txs = scan_block(
|
||||
&consensus::MainNetwork,
|
||||
cb,
|
||||
&[],
|
||||
&[(&nf, account)],
|
||||
&mut tree,
|
||||
&mut [],
|
||||
);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
|
|
@ -9,6 +9,7 @@ use zcash_client_backend::{
|
|||
proto::compact_formats::CompactBlock, welding_rig::scan_block,
|
||||
};
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
sapling::Node,
|
||||
transaction::Transaction,
|
||||
|
@ -188,6 +189,7 @@ pub fn scan_cached_blocks<P: AsRef<Path>, Q: AsRef<Path>>(
|
|||
let nf_refs: Vec<_> = nullifiers.iter().map(|(nf, acc)| (&nf[..], *acc)).collect();
|
||||
let mut witness_refs: Vec<_> = witnesses.iter_mut().map(|w| &mut w.witness).collect();
|
||||
scan_block(
|
||||
&consensus::MainNetwork,
|
||||
block,
|
||||
&extfvks[..],
|
||||
&nf_refs,
|
||||
|
@ -372,7 +374,7 @@ pub fn decrypt_and_store_transaction<P: AsRef<Path>>(
|
|||
.collect::<Result<Result<Option<_>, _>, _>>()??
|
||||
.ok_or(Error(ErrorKind::IncorrectHRPExtFVK))?;
|
||||
|
||||
let outputs = decrypt_transaction(tx, &extfvks);
|
||||
let outputs = decrypt_transaction(&consensus::MainNetwork, tx, &extfvks);
|
||||
|
||||
if outputs.is_empty() {
|
||||
// Nothing to see here
|
||||
|
|
|
@ -5,10 +5,10 @@ use std::fmt;
|
|||
|
||||
/// Zcash consensus parameters.
|
||||
pub trait Parameters {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32>;
|
||||
fn activation_height(&self, nu: NetworkUpgrade) -> Option<u32>;
|
||||
|
||||
fn is_nu_active(nu: NetworkUpgrade, height: u32) -> bool {
|
||||
match Self::activation_height(nu) {
|
||||
fn is_nu_active(&self, nu: NetworkUpgrade, height: u32) -> bool {
|
||||
match self.activation_height(nu) {
|
||||
Some(h) if h <= height => true,
|
||||
_ => false,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub trait Parameters {
|
|||
pub struct MainNetwork;
|
||||
|
||||
impl Parameters for MainNetwork {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32> {
|
||||
fn activation_height(&self, nu: NetworkUpgrade) -> Option<u32> {
|
||||
match nu {
|
||||
NetworkUpgrade::Overwinter => Some(347_500),
|
||||
NetworkUpgrade::Sapling => Some(419_200),
|
||||
|
@ -36,7 +36,7 @@ impl Parameters for MainNetwork {
|
|||
pub struct TestNetwork;
|
||||
|
||||
impl Parameters for TestNetwork {
|
||||
fn activation_height(nu: NetworkUpgrade) -> Option<u32> {
|
||||
fn activation_height(&self, nu: NetworkUpgrade) -> Option<u32> {
|
||||
match nu {
|
||||
NetworkUpgrade::Overwinter => Some(207_500),
|
||||
NetworkUpgrade::Sapling => Some(280_000),
|
||||
|
@ -174,9 +174,9 @@ impl BranchId {
|
|||
/// the given height.
|
||||
///
|
||||
/// This is the branch ID that should be used when creating transactions.
|
||||
pub fn for_height<C: Parameters>(height: u32) -> Self {
|
||||
pub fn for_height<C: Parameters>(parameters: C, height: u32) -> Self {
|
||||
for nu in UPGRADES_IN_ORDER.iter().rev() {
|
||||
if C::is_nu_active(*nu, height) {
|
||||
if parameters.is_nu_active(*nu, height) {
|
||||
return nu.branch_id();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Implementation of in-band secret distribution for Zcash transactions.
|
||||
|
||||
use crate::{
|
||||
consensus,
|
||||
consensus::NetworkUpgrade,
|
||||
jubjub::{
|
||||
edwards,
|
||||
fs::{Fs, FsRepr},
|
||||
|
@ -335,7 +337,9 @@ impl SaplingNoteEncryption {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_note_plaintext_without_memo(
|
||||
fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
height: u32,
|
||||
ivk: &Fs,
|
||||
cmu: &Fr,
|
||||
plaintext: &[u8],
|
||||
|
@ -380,7 +384,9 @@ fn parse_note_plaintext_without_memo(
|
|||
/// `PaymentAddress` to which the note was sent.
|
||||
///
|
||||
/// Implements section 4.17.2 of the Zcash Protocol Specification.
|
||||
pub fn try_sapling_note_decryption(
|
||||
pub fn try_sapling_note_decryption<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
height: u32,
|
||||
ivk: &Fs,
|
||||
epk: &edwards::Point<Bls12, PrimeOrder>,
|
||||
cmu: &Fr,
|
||||
|
@ -405,7 +411,7 @@ pub fn try_sapling_note_decryption(
|
|||
NOTE_PLAINTEXT_SIZE
|
||||
);
|
||||
|
||||
let (note, to) = parse_note_plaintext_without_memo(ivk, cmu, &plaintext)?;
|
||||
let (note, to) = parse_note_plaintext_without_memo(parameters, height, ivk, cmu, &plaintext)?;
|
||||
|
||||
let mut memo = [0u8; 512];
|
||||
memo.copy_from_slice(&plaintext[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]);
|
||||
|
@ -422,7 +428,9 @@ pub fn try_sapling_note_decryption(
|
|||
/// Implements the procedure specified in [`ZIP 307`].
|
||||
///
|
||||
/// [`ZIP 307`]: https://github.com/zcash/zips/pull/226
|
||||
pub fn try_sapling_compact_note_decryption(
|
||||
pub fn try_sapling_compact_note_decryption<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
height: u32,
|
||||
ivk: &Fs,
|
||||
epk: &edwards::Point<Bls12, PrimeOrder>,
|
||||
cmu: &Fr,
|
||||
|
@ -438,7 +446,7 @@ pub fn try_sapling_compact_note_decryption(
|
|||
plaintext.copy_from_slice(&enc_ciphertext);
|
||||
ChaCha20Ietf::xor(key.as_bytes(), &[0u8; 12], 1, &mut plaintext);
|
||||
|
||||
parse_note_plaintext_without_memo(ivk, cmu, &plaintext)
|
||||
parse_note_plaintext_without_memo(parameters, height, ivk, cmu, &plaintext)
|
||||
}
|
||||
|
||||
/// Recovery of the full note plaintext by the sender.
|
||||
|
@ -448,7 +456,9 @@ pub fn try_sapling_compact_note_decryption(
|
|||
/// `PaymentAddress` to which the note was sent.
|
||||
///
|
||||
/// Implements section 4.17.3 of the Zcash Protocol Specification.
|
||||
pub fn try_sapling_output_recovery(
|
||||
pub fn try_sapling_output_recovery<P: consensus::Parameters>(
|
||||
parameters: &P,
|
||||
height: u32,
|
||||
ovk: &OutgoingViewingKey,
|
||||
cv: &edwards::Point<Bls12, Unknown>,
|
||||
cmu: &Fr,
|
||||
|
@ -717,6 +727,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn random_enc_ciphertext_with<R: RngCore + CryptoRng>(
|
||||
height: u32,
|
||||
ivk: Fs,
|
||||
mut rng: &mut R,
|
||||
) -> (
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::fmt;
|
|||
|
||||
use crate::{
|
||||
consensus,
|
||||
consensus::NetworkUpgrade,
|
||||
keys::OutgoingViewingKey,
|
||||
legacy::TransparentAddress,
|
||||
merkle_tree::MerklePath,
|
||||
|
@ -86,7 +87,9 @@ pub struct SaplingOutput {
|
|||
}
|
||||
|
||||
impl SaplingOutput {
|
||||
pub fn new<R: RngCore + CryptoRng>(
|
||||
pub fn new<R: RngCore + CryptoRng, P: consensus::Parameters>(
|
||||
parameters: P,
|
||||
height: u32,
|
||||
rng: &mut R,
|
||||
ovk: OutgoingViewingKey,
|
||||
to: PaymentAddress<Bls12>,
|
||||
|
@ -304,6 +307,7 @@ impl TransactionMetadata {
|
|||
/// Generates a [`Transaction`] from its inputs and outputs.
|
||||
pub struct Builder<R: RngCore + CryptoRng> {
|
||||
rng: R,
|
||||
height: u32,
|
||||
mtx: TransactionData,
|
||||
fee: Amount,
|
||||
anchor: Option<Fr>,
|
||||
|
@ -344,6 +348,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
|
||||
Builder {
|
||||
rng,
|
||||
height,
|
||||
mtx,
|
||||
fee: DEFAULT_FEE,
|
||||
anchor: None,
|
||||
|
@ -399,7 +404,15 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
value: Amount,
|
||||
memo: Option<Memo>,
|
||||
) -> Result<(), Error> {
|
||||
let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?;
|
||||
let output = SaplingOutput::new(
|
||||
consensus::MainNetwork,
|
||||
self.height,
|
||||
&mut self.rng,
|
||||
ovk,
|
||||
to,
|
||||
value,
|
||||
memo,
|
||||
)?;
|
||||
|
||||
self.mtx.value_balance -= value;
|
||||
|
||||
|
|
Loading…
Reference in New Issue