zcash_client_sqlite: Allow multi-output fake blocks to send to multiple keys.

This commit is contained in:
Kris Nuttycombe 2024-05-01 12:44:59 -06:00
parent c88cd17929
commit 3db515e347
4 changed files with 112 additions and 18 deletions

View File

@ -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<Fvk: TestFvk>(
&mut self,
outputs: &[FakeCompactOutput<Fvk>],
) -> (BlockHeight, Cache::InsertResult, Vec<Fvk::Nullifier>) {
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<Fvk>],
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<sapling::keys::OutgoingViewingKey> {
(*self).sapling_ovk()
}
#[cfg(feature = "orchard")]
fn orchard_ovk(&self, scope: zip32::Scope) -> Option<orchard::keys::OutgoingViewingKey> {
(*self).orchard_ovk(scope)
}
fn add_spend<R: RngCore + CryptoRng>(
&self,
ctx: &mut CompactTx,
nf: Self::Nullifier,
rng: &mut R,
) {
(*self).add_spend(ctx, nf, rng)
}
fn add_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
&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<P: consensus::Parameters, R: RngCore + CryptoRng>(
&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<R: RngCore + CryptoRng>(rng: &mut R) -> CompactTx {
ctx
}
pub(crate) struct FakeCompactOutput {
#[derive(Clone)]
pub(crate) struct FakeCompactOutput<Fvk> {
fvk: Fvk,
address_type: AddressType,
value: NonNegativeAmount,
}
impl FakeCompactOutput {
pub(crate) fn new(address_type: AddressType, value: NonNegativeAmount) -> Self {
impl<Fvk> FakeCompactOutput<Fvk> {
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<P: consensus::Parameters, Fvk: TestFvk>(
params: &P,
height: BlockHeight,
prev_hash: BlockHash,
fvk: &Fvk,
outputs: &[FakeCompactOutput],
outputs: &[FakeCompactOutput<Fvk>],
initial_sapling_tree_size: u32,
initial_orchard_tree_size: u32,
mut rng: impl RngCore + CryptoRng,
@ -1624,7 +1715,7 @@ fn fake_compact_block<P: consensus::Parameters, Fvk: TestFvk>(
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,

View File

@ -1376,8 +1376,8 @@ pub(crate) fn checkpoint_gaps<T: ShieldedPoolTester>() {
st.generate_block_at(
account.birthday().height() + 10,
BlockHash([0; 32]),
&not_our_key,
&[FakeCompactOutput::new(
&not_our_key,
AddressType::DefaultExternal,
not_our_value,
)],
@ -1960,8 +1960,8 @@ pub(crate) fn invalid_chain_cache_disconnected<T: ShieldedPoolTester>() {
st.generate_block_at(
disconnect_height,
BlockHash([1; 32]),
&dfvk,
&[FakeCompactOutput::new(
&dfvk,
AddressType::DefaultExternal,
NonNegativeAmount::const_from_u64(8),
)],

View File

@ -3208,8 +3208,8 @@ mod tests {
let _ = st.generate_block_at(
start_height,
BlockHash([0; 32]),
&not_our_key,
&[FakeCompactOutput::new(
&not_our_key,
AddressType::DefaultExternal,
not_our_value,
)],

View File

@ -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),
)],