From 3db515e347fe446908e3d29f7d71f4219ec220c5 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Wed, 1 May 2024 12:44:59 -0600 Subject: [PATCH] zcash_client_sqlite: Allow multi-output fake blocks to send to multiple keys. --- zcash_client_sqlite/src/testing.rs | 113 +++++++++++++++++++-- zcash_client_sqlite/src/testing/pool.rs | 4 +- zcash_client_sqlite/src/wallet.rs | 2 +- zcash_client_sqlite/src/wallet/scanning.rs | 11 +- 4 files changed, 112 insertions(+), 18 deletions(-) diff --git a/zcash_client_sqlite/src/testing.rs b/zcash_client_sqlite/src/testing.rs index 8f85f4c1e..772b57026 100644 --- a/zcash_client_sqlite/src/testing.rs +++ b/zcash_client_sqlite/src/testing.rs @@ -471,8 +471,7 @@ where let (res, nfs) = self.generate_block_at( height, prior_cached_block.chain_state.block_hash(), - fvk, - &[FakeCompactOutput::new(address_type, value)], + &[FakeCompactOutput::new(fvk, address_type, value)], prior_cached_block.sapling_end_size, prior_cached_block.orchard_end_size, false, @@ -481,6 +480,28 @@ where (height, res, nfs[0]) } + /// Creates a fake block at the expected next height containing multiple outputs + /// and inserts it into the cache. + pub(crate) fn generate_next_block_multi( + &mut self, + outputs: &[FakeCompactOutput], + ) -> (BlockHeight, Cache::InsertResult, Vec) { + let pre_activation_block = CachedBlock::none(self.sapling_activation_height() - 1); + let prior_cached_block = self.latest_cached_block().unwrap_or(&pre_activation_block); + let height = prior_cached_block.height() + 1; + + let (res, nfs) = self.generate_block_at( + height, + prior_cached_block.chain_state.block_hash(), + outputs, + prior_cached_block.sapling_end_size, + prior_cached_block.orchard_end_size, + false, + ); + + (height, res, nfs) + } + /// Adds an empty block to the cache, advancing the simulated chain height. #[allow(dead_code)] // used only for tests that are flagged off by default pub(crate) fn generate_empty_block(&mut self) -> (BlockHeight, Cache::InsertResult) { @@ -526,8 +547,7 @@ where &mut self, height: BlockHeight, prev_hash: BlockHash, - fvk: &Fvk, - outputs: &[FakeCompactOutput], + outputs: &[FakeCompactOutput], initial_sapling_tree_size: u32, initial_orchard_tree_size: u32, allow_broken_hash_chain: bool, @@ -589,7 +609,6 @@ where &self.network(), height, prev_hash, - fvk, outputs, initial_sapling_tree_size, initial_orchard_tree_size, @@ -1333,6 +1352,76 @@ pub(crate) trait TestFvk { ) -> Self::Nullifier; } +impl<'a, A: TestFvk> TestFvk for &'a A { + type Nullifier = A::Nullifier; + + fn sapling_ovk(&self) -> Option { + (*self).sapling_ovk() + } + + #[cfg(feature = "orchard")] + fn orchard_ovk(&self, scope: zip32::Scope) -> Option { + (*self).orchard_ovk(scope) + } + + fn add_spend( + &self, + ctx: &mut CompactTx, + nf: Self::Nullifier, + rng: &mut R, + ) { + (*self).add_spend(ctx, nf, rng) + } + + fn add_output( + &self, + ctx: &mut CompactTx, + params: &P, + height: BlockHeight, + req: AddressType, + value: Zatoshis, + initial_sapling_tree_size: u32, + // we don't require an initial Orchard tree size because we don't need it to compute + // the nullifier. + rng: &mut R, + ) -> Self::Nullifier { + (*self).add_output( + ctx, + params, + height, + req, + value, + initial_sapling_tree_size, + rng, + ) + } + + fn add_logical_action( + &self, + ctx: &mut CompactTx, + params: &P, + height: BlockHeight, + nf: Self::Nullifier, + req: AddressType, + value: Zatoshis, + initial_sapling_tree_size: u32, + // we don't require an initial Orchard tree size because we don't need it to compute + // the nullifier. + rng: &mut R, + ) -> Self::Nullifier { + (*self).add_logical_action( + ctx, + params, + height, + nf, + req, + value, + initial_sapling_tree_size, + rng, + ) + } +} + impl TestFvk for DiversifiableFullViewingKey { type Nullifier = Nullifier; @@ -1591,14 +1680,17 @@ fn fake_compact_tx(rng: &mut R) -> CompactTx { ctx } -pub(crate) struct FakeCompactOutput { +#[derive(Clone)] +pub(crate) struct FakeCompactOutput { + fvk: Fvk, address_type: AddressType, value: NonNegativeAmount, } -impl FakeCompactOutput { - pub(crate) fn new(address_type: AddressType, value: NonNegativeAmount) -> Self { +impl FakeCompactOutput { + pub(crate) fn new(fvk: Fvk, address_type: AddressType, value: NonNegativeAmount) -> Self { Self { + fvk, address_type, value, } @@ -1614,8 +1706,7 @@ fn fake_compact_block( params: &P, height: BlockHeight, prev_hash: BlockHash, - fvk: &Fvk, - outputs: &[FakeCompactOutput], + outputs: &[FakeCompactOutput], initial_sapling_tree_size: u32, initial_orchard_tree_size: u32, mut rng: impl RngCore + CryptoRng, @@ -1624,7 +1715,7 @@ fn fake_compact_block( let mut ctx = fake_compact_tx(&mut rng); let mut nfs = vec![]; for output in outputs { - let nf = fvk.add_output( + let nf = output.fvk.add_output( &mut ctx, params, height, diff --git a/zcash_client_sqlite/src/testing/pool.rs b/zcash_client_sqlite/src/testing/pool.rs index 636f26e2e..d1e53881f 100644 --- a/zcash_client_sqlite/src/testing/pool.rs +++ b/zcash_client_sqlite/src/testing/pool.rs @@ -1376,8 +1376,8 @@ pub(crate) fn checkpoint_gaps() { st.generate_block_at( account.birthday().height() + 10, BlockHash([0; 32]), - ¬_our_key, &[FakeCompactOutput::new( + ¬_our_key, AddressType::DefaultExternal, not_our_value, )], @@ -1960,8 +1960,8 @@ pub(crate) fn invalid_chain_cache_disconnected() { st.generate_block_at( disconnect_height, BlockHash([1; 32]), - &dfvk, &[FakeCompactOutput::new( + &dfvk, AddressType::DefaultExternal, NonNegativeAmount::const_from_u64(8), )], diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index f576b499b..dbbede4b3 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -3208,8 +3208,8 @@ mod tests { let _ = st.generate_block_at( start_height, BlockHash([0; 32]), - ¬_our_key, &[FakeCompactOutput::new( + ¬_our_key, AddressType::DefaultExternal, not_our_value, )], diff --git a/zcash_client_sqlite/src/wallet/scanning.rs b/zcash_client_sqlite/src/wallet/scanning.rs index 926a6b1b3..3f17f8a18 100644 --- a/zcash_client_sqlite/src/wallet/scanning.rs +++ b/zcash_client_sqlite/src/wallet/scanning.rs @@ -694,8 +694,11 @@ pub(crate) mod tests { st.generate_block_at( initial_height, prior_block_hash, - &dfvk, - &[FakeCompactOutput::new(AddressType::DefaultExternal, value)], + &[FakeCompactOutput::new( + &dfvk, + AddressType::DefaultExternal, + value, + )], initial_sapling_tree_size, initial_orchard_tree_size, false, @@ -1101,8 +1104,8 @@ pub(crate) mod tests { st.generate_block_at( max_scanned, BlockHash([1u8; 32]), - &dfvk, &[FakeCompactOutput::new( + &dfvk, AddressType::DefaultExternal, // 1235 notes into into the second shard NonNegativeAmount::const_from_u64(10000), @@ -1291,8 +1294,8 @@ pub(crate) mod tests { st.generate_block_at( max_scanned, BlockHash([1; 32]), - &dfvk, &[FakeCompactOutput::new( + &dfvk, AddressType::DefaultExternal, NonNegativeAmount::const_from_u64(10000), )],