zcash_client_backend: Use a polymorphic type for `ScannedBlock` note commitment and nullifier data.

This commit is contained in:
Kris Nuttycombe 2024-01-04 11:15:43 -07:00
parent f18d082aa3
commit 857e44a11c
3 changed files with 29 additions and 74 deletions

View File

@ -14,8 +14,7 @@ and this library adheres to Rust's notion of
- `SaplingInputSource` - `SaplingInputSource`
- `ScannedBlock::{into_commitments, sapling}` - `ScannedBlock::{into_commitments, sapling}`
- `ScannedBlock::orchard` (when the `orchard` feature is enabled.) - `ScannedBlock::orchard` (when the `orchard` feature is enabled.)
- `ScannedBlockSapling` - `ScannedBundles`
- `ScannedBlockOrchard` (when the `orchard` feature is enabled.)
- `ScannedBlockCommitments` - `ScannedBlockCommitments`
- `Balance::{add_spendable_value, add_pending_change_value, add_pending_spendable_value}` - `Balance::{add_spendable_value, add_pending_change_value, add_pending_spendable_value}`
- `AccountBalance::{ - `AccountBalance::{

View File

@ -601,21 +601,22 @@ impl BlockMetadata {
} }
} }
/// The Sapling note commitment and nullifier data extracted from a [`CompactBlock`] that is /// The protocol-specific note commitment and nullifier data extracted from the per-transaction
/// required by the wallet for note commitment tree maintenance and spend detection. /// shielded bundles in [`CompactBlock`], used by the wallet for note commitment tree maintenance
/// and spend detection.
/// ///
/// [`CompactBlock`]: crate::proto::compact_formats::CompactBlock /// [`CompactBlock`]: crate::proto::compact_formats::CompactBlock
pub struct ScannedBlockSapling { pub struct ScannedBundles<NoteCommitment, NF> {
final_tree_size: u32, final_tree_size: u32,
commitments: Vec<(sapling::Node, Retention<BlockHeight>)>, commitments: Vec<(NoteCommitment, Retention<BlockHeight>)>,
nullifier_map: Vec<(TxId, u16, Vec<sapling::Nullifier>)>, nullifier_map: Vec<(TxId, u16, Vec<NF>)>,
} }
impl ScannedBlockSapling { impl<NoteCommitment, NF> ScannedBundles<NoteCommitment, NF> {
pub(crate) fn new( pub(crate) fn new(
final_tree_size: u32, final_tree_size: u32,
commitments: Vec<(sapling::Node, Retention<BlockHeight>)>, commitments: Vec<(NoteCommitment, Retention<BlockHeight>)>,
nullifier_map: Vec<(TxId, u16, Vec<sapling::Nullifier>)>, nullifier_map: Vec<(TxId, u16, Vec<NF>)>,
) -> Self { ) -> Self {
Self { Self {
final_tree_size, final_tree_size,
@ -624,71 +625,24 @@ impl ScannedBlockSapling {
} }
} }
/// Returns the size of the Sapling note commitment tree as of the end of the scanned block. /// Returns the size of the note commitment tree as of the end of the scanned block.
pub fn final_tree_size(&self) -> u32 { pub fn final_tree_size(&self) -> u32 {
self.final_tree_size self.final_tree_size
} }
/// Returns the vector of Sapling nullifiers for each transaction in the block. /// Returns the vector of nullifiers for each transaction in the block.
/// ///
/// The returned tuple is keyed by both transaction ID and the index of the transaction within /// The returned tuple is keyed by both transaction ID and the index of the transaction within
/// the block, so that either the txid or the combination of the block hash available from /// the block, so that either the txid or the combination of the block hash available from
/// [`Self::block_hash`] and returned transaction index may be used to uniquely identify the /// [`Self::block_hash`] and returned transaction index may be used to uniquely identify the
/// transaction, depending upon the needs of the caller. /// transaction, depending upon the needs of the caller.
pub fn nullifier_map(&self) -> &[(TxId, u16, Vec<sapling::Nullifier>)] { pub fn nullifier_map(&self) -> &[(TxId, u16, Vec<NF>)] {
&self.nullifier_map &self.nullifier_map
} }
/// Returns the ordered list of Sapling note commitments to be added to the note commitment /// Returns the ordered list of note commitments to be added to the note commitment
/// tree. /// tree.
pub fn commitments(&self) -> &[(sapling::Node, Retention<BlockHeight>)] { pub fn commitments(&self) -> &[(NoteCommitment, Retention<BlockHeight>)] {
&self.commitments
}
}
/// The Orchard note commitment and nullifier data extracted from a [`CompactBlock`] that is
/// required by the wallet for note commitment tree maintenance and spend detection.
///
/// [`CompactBlock`]: crate::proto::compact_formats::CompactBlock
#[cfg(feature = "orchard")]
pub struct ScannedBlockOrchard {
final_tree_size: u32,
nullifier_map: Vec<(TxId, u16, Vec<orchard::note::Nullifier>)>,
commitments: Vec<(orchard::note::NoteCommitment, Retention<BlockHeight>)>,
}
#[cfg(feature = "orchard")]
impl ScannedBlockOrchard {
pub(crate) fn new(
final_tree_size: u32,
nullifier_map: Vec<(TxId, u16, Vec<orchard::note::Nullifier>)>,
commitments: Vec<(orchard::note::NoteCommitment, Retention<BlockHeight>)>,
) -> Self {
Self {
final_tree_size,
nullifier_map,
commitments,
}
}
/// Returns the size of the Orchard note commitment tree as of the end of the scanned block.
pub fn final_tree_size(&self) -> u32 {
self.final_tree_size
}
/// Returns the vector of Orchard nullifiers for each transaction in the block.
///
/// The returned tuple is keyed by both transaction ID and the index of the transaction within
/// the block, so that either the txid or the combination of the block hash available from
/// [`Self::block_hash`] and returned transaction index may be used to uniquely identify the
/// transaction, depending upon the needs of the caller.
pub fn nullifier_map(&self) -> &[(TxId, u16, Vec<orchard::note::Nullifier>)] {
&self.nullifier_map
}
/// Returns the ordered list of Orchard note commitments to be added to the note commitment
/// tree.
pub fn commitments(&self) -> &[(orchard::note::NoteCommitment, Retention<BlockHeight>)] {
&self.commitments &self.commitments
} }
} }
@ -713,9 +667,9 @@ pub struct ScannedBlock<Nf, S> {
block_hash: BlockHash, block_hash: BlockHash,
block_time: u32, block_time: u32,
transactions: Vec<WalletTx<Nf, S>>, transactions: Vec<WalletTx<Nf, S>>,
sapling: ScannedBlockSapling, sapling: ScannedBundles<sapling::Node, sapling::Nullifier>,
#[cfg(feature = "orchard")] #[cfg(feature = "orchard")]
orchard: ScannedBlockOrchard, orchard: ScannedBundles<orchard::note::NoteCommitment, orchard::note::Nullifier>,
} }
impl<Nf, S> ScannedBlock<Nf, S> { impl<Nf, S> ScannedBlock<Nf, S> {
@ -725,8 +679,11 @@ impl<Nf, S> ScannedBlock<Nf, S> {
block_hash: BlockHash, block_hash: BlockHash,
block_time: u32, block_time: u32,
transactions: Vec<WalletTx<Nf, S>>, transactions: Vec<WalletTx<Nf, S>>,
sapling: ScannedBlockSapling, sapling: ScannedBundles<sapling::Node, sapling::Nullifier>,
#[cfg(feature = "orchard")] orchard: ScannedBlockOrchard, #[cfg(feature = "orchard")] orchard: ScannedBundles<
orchard::note::NoteCommitment,
orchard::note::Nullifier,
>,
) -> Self { ) -> Self {
Self { Self {
block_height, block_height,
@ -760,13 +717,15 @@ impl<Nf, S> ScannedBlock<Nf, S> {
} }
/// Returns the Sapling note commitment tree and nullifier data for the block. /// Returns the Sapling note commitment tree and nullifier data for the block.
pub fn sapling(&self) -> &ScannedBlockSapling { pub fn sapling(&self) -> &ScannedBundles<sapling::Node, sapling::Nullifier> {
&self.sapling &self.sapling
} }
/// Returns the Orchard note commitment tree and nullifier data for the block. /// Returns the Orchard note commitment tree and nullifier data for the block.
#[cfg(feature = "orchard")] #[cfg(feature = "orchard")]
pub fn orchard(&self) -> &ScannedBlockOrchard { pub fn orchard(
&self,
) -> &ScannedBundles<orchard::note::NoteCommitment, orchard::note::Nullifier> {
&self.orchard &self.orchard
} }

View File

@ -18,7 +18,7 @@ use zcash_primitives::{
zip32::{AccountId, Scope}, zip32::{AccountId, Scope},
}; };
use crate::data_api::{BlockMetadata, ScannedBlock, ScannedBlockSapling}; use crate::data_api::{BlockMetadata, ScannedBlock, ScannedBundles};
use crate::{ use crate::{
proto::compact_formats::CompactBlock, proto::compact_formats::CompactBlock,
scan::{Batch, BatchRunner, Tasks}, scan::{Batch, BatchRunner, Tasks},
@ -26,9 +26,6 @@ use crate::{
ShieldedProtocol, ShieldedProtocol,
}; };
#[cfg(feature = "orchard")]
use crate::data_api::ScannedBlockOrchard;
/// A key that can be used to perform trial decryption and nullifier /// A key that can be used to perform trial decryption and nullifier
/// computation for a Sapling [`CompactSaplingOutput`] /// computation for a Sapling [`CompactSaplingOutput`]
/// ///
@ -651,13 +648,13 @@ pub(crate) fn scan_block_with_runner<
cur_hash, cur_hash,
block.time, block.time,
wtxs, wtxs,
ScannedBlockSapling::new( ScannedBundles::new(
sapling_commitment_tree_size, sapling_commitment_tree_size,
sapling_note_commitments, sapling_note_commitments,
sapling_nullifier_map, sapling_nullifier_map,
), ),
#[cfg(feature = "orchard")] #[cfg(feature = "orchard")]
ScannedBlockOrchard::new( ScannedBundles::new(
orchard_commitment_tree_size, orchard_commitment_tree_size,
vec![], // FIXME: collect the Orchard nullifiers vec![], // FIXME: collect the Orchard nullifiers
vec![], // FIXME: collect the Orchard note commitments vec![], // FIXME: collect the Orchard note commitments