Add tests for batched note decryption.

This commit is contained in:
Kris Nuttycombe 2022-08-18 15:03:32 -06:00
parent 6156215d4c
commit 397c76ca8d
2 changed files with 148 additions and 91 deletions

View File

@ -77,15 +77,13 @@
//! # } //! # }
//! ``` //! ```
use std::convert::TryFrom;
use std::fmt::Debug; use std::fmt::Debug;
use zcash_primitives::{ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus::{self, BlockHeight, NetworkUpgrade}, consensus::{self, BlockHeight, NetworkUpgrade},
merkle_tree::CommitmentTree, merkle_tree::CommitmentTree,
sapling::{keys::Scope, note_encryption::SaplingDomain, Nullifier}, sapling::{keys::Scope, Nullifier},
transaction::components::sapling::CompactOutputDescription,
}; };
use crate::{ use crate::{
@ -96,7 +94,7 @@ use crate::{
proto::compact_formats::CompactBlock, proto::compact_formats::CompactBlock,
scan::BatchRunner, scan::BatchRunner,
wallet::WalletTx, wallet::WalletTx,
welding_rig::scan_block_with_runner, welding_rig::{add_block_to_runner, scan_block_with_runner},
}; };
/// Checks that the scanned blocks in the data database, when combined with the recent /// Checks that the scanned blocks in the data database, when combined with the recent
@ -241,28 +239,7 @@ where
); );
cache.with_blocks(last_height, limit, |block: CompactBlock| { cache.with_blocks(last_height, limit, |block: CompactBlock| {
let block_hash = block.hash(); add_block_to_runner(params, block, &mut batch_runner);
let block_height = block.height();
for tx in block.vtx.into_iter() {
let txid = tx.txid();
let outputs = tx
.outputs
.into_iter()
.map(|output| {
CompactOutputDescription::try_from(output)
.expect("Invalid output found in compact block decoding.")
})
.collect::<Vec<_>>();
batch_runner.add_outputs(
block_hash,
txid,
|| SaplingDomain::for_height(params.clone(), block_height),
&outputs,
)
}
Ok(()) Ok(())
})?; })?;

View File

@ -163,6 +163,34 @@ pub fn scan_block<P: consensus::Parameters + Send + 'static, K: ScanningKey>(
) )
} }
pub(crate) fn add_block_to_runner<P: consensus::Parameters + Send + 'static>(
params: &P,
block: CompactBlock,
batch_runner: &mut BatchRunner<SaplingDomain<P>, CompactOutputDescription>,
) {
let block_hash = block.hash();
let block_height = block.height();
for tx in block.vtx.into_iter() {
let txid = tx.txid();
let outputs = tx
.outputs
.into_iter()
.map(|output| {
CompactOutputDescription::try_from(output)
.expect("Invalid output found in compact block decoding.")
})
.collect::<Vec<_>>();
batch_runner.add_outputs(
block_hash,
txid,
|| SaplingDomain::for_height(params.clone(), block_height),
&outputs,
)
}
}
pub(crate) fn scan_block_with_runner<P: consensus::Parameters + Send + 'static, K: ScanningKey>( pub(crate) fn scan_block_with_runner<P: consensus::Parameters + Send + 'static, K: ScanningKey>(
params: &P, params: &P,
block: CompactBlock, block: CompactBlock,
@ -371,11 +399,15 @@ mod tests {
zip32::{AccountId, ExtendedFullViewingKey, ExtendedSpendingKey}, zip32::{AccountId, ExtendedFullViewingKey, ExtendedSpendingKey},
}; };
use super::scan_block; use crate::{
use crate::proto::compact_formats::{ proto::compact_formats::{
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx, CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
},
scan::BatchRunner,
}; };
use super::{add_block_to_runner, scan_block, scan_block_with_runner, ScanningKey};
fn random_compact_tx(mut rng: impl RngCore) -> CompactTx { fn random_compact_tx(mut rng: impl RngCore) -> CompactTx {
let fake_nf = { let fake_nf = {
let mut nf = vec![0; 32]; let mut nf = vec![0; 32];
@ -483,80 +515,128 @@ mod tests {
#[test] #[test]
fn scan_block_with_my_tx() { fn scan_block_with_my_tx() {
let extsk = ExtendedSpendingKey::master(&[]); fn go(scan_multithreaded: bool) {
let extfvk = ExtendedFullViewingKey::from(&extsk); let extsk = ExtendedSpendingKey::master(&[]);
let extfvk = ExtendedFullViewingKey::from(&extsk);
let cb = fake_compact_block( let cb = fake_compact_block(
1u32.into(), 1u32.into(),
Nullifier([0; 32]), Nullifier([0; 32]),
extfvk.clone(), extfvk.clone(),
Amount::from_u64(5).unwrap(), Amount::from_u64(5).unwrap(),
false, false,
); );
assert_eq!(cb.vtx.len(), 2); assert_eq!(cb.vtx.len(), 2);
let mut tree = CommitmentTree::empty(); let mut tree = CommitmentTree::empty();
let txs = scan_block( let mut batch_runner = if scan_multithreaded {
&Network::TestNetwork, let mut runner = BatchRunner::new(
cb, 10,
&[(&AccountId::from(0), &extfvk)], extfvk
&[], .to_sapling_keys()
&mut tree, .iter()
&mut [], .map(|(k, _)| k.clone())
); .collect(),
assert_eq!(txs.len(), 1); );
let tx = &txs[0]; add_block_to_runner(&Network::TestNetwork, cb.clone(), &mut runner);
assert_eq!(tx.index, 1); runner.flush();
assert_eq!(tx.num_spends, 1);
assert_eq!(tx.num_outputs, 1);
assert_eq!(tx.shielded_spends.len(), 0);
assert_eq!(tx.shielded_outputs.len(), 1);
assert_eq!(tx.shielded_outputs[0].index, 0);
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
assert_eq!(tx.shielded_outputs[0].note.value, 5);
// Check that the witness root matches Some(runner)
assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root()); } else {
None
};
let txs = scan_block_with_runner(
&Network::TestNetwork,
cb,
&[(&AccountId::from(0), &extfvk)],
&[],
&mut tree,
&mut [],
batch_runner.as_mut(),
);
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.index, 1);
assert_eq!(tx.num_spends, 1);
assert_eq!(tx.num_outputs, 1);
assert_eq!(tx.shielded_spends.len(), 0);
assert_eq!(tx.shielded_outputs.len(), 1);
assert_eq!(tx.shielded_outputs[0].index, 0);
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
assert_eq!(tx.shielded_outputs[0].note.value, 5);
// Check that the witness root matches
assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root());
}
go(false);
go(true);
} }
#[test] #[test]
fn scan_block_with_txs_after_my_tx() { fn scan_block_with_txs_after_my_tx() {
let extsk = ExtendedSpendingKey::master(&[]); fn go(scan_multithreaded: bool) {
let extfvk = ExtendedFullViewingKey::from(&extsk); let extsk = ExtendedSpendingKey::master(&[]);
let extfvk = ExtendedFullViewingKey::from(&extsk);
let cb = fake_compact_block( let cb = fake_compact_block(
1u32.into(), 1u32.into(),
Nullifier([0; 32]), Nullifier([0; 32]),
extfvk.clone(), extfvk.clone(),
Amount::from_u64(5).unwrap(), Amount::from_u64(5).unwrap(),
true, true,
); );
assert_eq!(cb.vtx.len(), 3); assert_eq!(cb.vtx.len(), 3);
let mut tree = CommitmentTree::empty(); let mut tree = CommitmentTree::empty();
let txs = scan_block( let mut batch_runner = if scan_multithreaded {
&Network::TestNetwork, let mut runner = BatchRunner::new(
cb, 10,
&[(&AccountId::from(0), &extfvk)], extfvk
&[], .to_sapling_keys()
&mut tree, .iter()
&mut [], .map(|(k, _)| k.clone())
); .collect(),
assert_eq!(txs.len(), 1); );
let tx = &txs[0]; add_block_to_runner(&Network::TestNetwork, cb.clone(), &mut runner);
assert_eq!(tx.index, 1); runner.flush();
assert_eq!(tx.num_spends, 1);
assert_eq!(tx.num_outputs, 1);
assert_eq!(tx.shielded_spends.len(), 0);
assert_eq!(tx.shielded_outputs.len(), 1);
assert_eq!(tx.shielded_outputs[0].index, 0);
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
assert_eq!(tx.shielded_outputs[0].note.value, 5);
// Check that the witness root matches Some(runner)
assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root()); } else {
None
};
let txs = scan_block_with_runner(
&Network::TestNetwork,
cb,
&[(&AccountId::from(0), &extfvk)],
&[],
&mut tree,
&mut [],
batch_runner.as_mut(),
);
assert_eq!(txs.len(), 1);
let tx = &txs[0];
assert_eq!(tx.index, 1);
assert_eq!(tx.num_spends, 1);
assert_eq!(tx.num_outputs, 1);
assert_eq!(tx.shielded_spends.len(), 0);
assert_eq!(tx.shielded_outputs.len(), 1);
assert_eq!(tx.shielded_outputs[0].index, 0);
assert_eq!(tx.shielded_outputs[0].account, AccountId::from(0));
assert_eq!(tx.shielded_outputs[0].note.value, 5);
// Check that the witness root matches
assert_eq!(tx.shielded_outputs[0].witness.root(), tree.root());
}
go(false);
go(true);
} }
#[test] #[test]