change(zebra-scan): Scan only one key per backend call (#8034)

* scan one key per backend call

* fix docs
This commit is contained in:
Alfredo Garcia 2023-11-29 21:51:32 -03:00 committed by GitHub
parent cb9452c5e3
commit 1708f9d946
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 6 additions and 77 deletions

View File

@ -70,7 +70,7 @@ pub async fn start(mut state: State, storage: Storage) -> Result<(), Report> {
} }
} }
/// Returns transactions belonging to any of the given [`ScanningKey`]s. /// Returns transactions belonging to the given `ScanningKey`.
/// ///
/// TODO: /// TODO:
/// - Remove the `sapling_tree_size` parameter or turn it into an `Option` once we have access to /// - Remove the `sapling_tree_size` parameter or turn it into an `Option` once we have access to
@ -80,7 +80,7 @@ pub fn scan_block<K: ScanningKey>(
network: Network, network: Network,
block: Arc<Block>, block: Arc<Block>,
sapling_tree_size: u32, sapling_tree_size: u32,
scanning_keys: &[&K], scanning_key: &K,
) -> Result<ScannedBlock<K::Nf>, ScanError> { ) -> Result<ScannedBlock<K::Nf>, ScanError> {
// TODO: Implement a check that returns early when the block height is below the Sapling // TODO: Implement a check that returns early when the block height is below the Sapling
// activation height. // activation height.
@ -96,10 +96,8 @@ pub fn scan_block<K: ScanningKey>(
// Use a dummy `AccountId` as we don't use accounts yet. // Use a dummy `AccountId` as we don't use accounts yet.
let dummy_account = AccountId::from(0); let dummy_account = AccountId::from(0);
let scanning_keys: Vec<_> = scanning_keys // We only support scanning one key and one block per function call for now.
.iter() let scanning_keys = vec![(&dummy_account, scanning_key)];
.map(|key| (&dummy_account, key))
.collect();
zcash_client_backend::scanning::scan_block( zcash_client_backend::scanning::scan_block(
&network, &network,

View File

@ -32,80 +32,11 @@ use zcash_primitives::{
}; };
use zebra_chain::{ use zebra_chain::{
block::Block, chain_tip::ChainTip, parameters::Network, serialization::ZcashDeserializeInto, block::Block, chain_tip::ChainTip, serialization::ZcashDeserializeInto, transaction::Hash,
transaction::Hash,
}; };
use crate::scan::{block_to_compact, scan_block}; use crate::scan::{block_to_compact, scan_block};
/// Scans a continuous chain of Mainnet blocks from tip to genesis.
///
/// Also verifies that no relevant transaction is found in the chain when scanning for a fake
/// account's nullifier.
#[tokio::test]
async fn scanning_from_populated_zebra_state() -> Result<()> {
let network = Network::default();
// Create a continuous chain of mainnet blocks from genesis
let blocks: Vec<Arc<Block>> = zebra_test::vectors::CONTINUOUS_MAINNET_BLOCKS
.iter()
.map(|(_height, block_bytes)| block_bytes.zcash_deserialize_into().unwrap())
.collect();
// Create a populated state service.
let (_state_service, read_only_state_service, latest_chain_tip, _chain_tip_change) =
zebra_state::populated_state(blocks.clone(), network).await;
let db = read_only_state_service.db();
// use the tip as starting height
let mut height = latest_chain_tip.best_tip_height().unwrap();
let mut transactions_found = 0;
let mut transactions_scanned = 0;
let mut blocks_scanned = 0;
// TODO: Accessing the state database directly is ok in the tests, but not in production code.
// Use `Request::Block` if the code is copied to production.
while let Some(block) = db.block(height.into()) {
// We use a dummy size of the Sapling note commitment tree. We can't set the size to zero
// because the underlying scanning function would return
// `zcash_client_backeng::scanning::ScanError::TreeSizeUnknown`.
let sapling_commitment_tree_size = 1;
let orchard_commitment_tree_size = 0;
let chain_metadata = ChainMetadata {
sapling_commitment_tree_size,
orchard_commitment_tree_size,
};
let compact_block = block_to_compact(block.clone(), chain_metadata);
let res =
scan_block::<SaplingIvk>(network, block, sapling_commitment_tree_size, &[]).unwrap();
transactions_found += res.transactions().len();
transactions_scanned += compact_block.vtx.len();
blocks_scanned += 1;
if height.is_min() {
break;
}
// scan backwards
height = height.previous()?;
}
// make sure all blocks and transactions were scanned
assert_eq!(blocks_scanned, 11);
assert_eq!(transactions_scanned, 11);
// no relevant transactions should be found
assert_eq!(transactions_found, 0);
Ok(())
}
/// Prove that we can create fake blocks with fake notes and scan them using the /// Prove that we can create fake blocks with fake notes and scan them using the
/// `zcash_client_backend::scanning::scan_block` function: /// `zcash_client_backend::scanning::scan_block` function:
/// - Function `fake_compact_block` will generate 1 block with one pre created fake nullifier in /// - Function `fake_compact_block` will generate 1 block with one pre created fake nullifier in
@ -207,7 +138,7 @@ async fn scanning_zecpages_from_populated_zebra_state() -> Result<()> {
let compact_block = block_to_compact(block.clone(), chain_metadata); let compact_block = block_to_compact(block.clone(), chain_metadata);
let res = scan_block(network, block, sapling_commitment_tree_size, &[&ivk]) let res = scan_block(network, block, sapling_commitment_tree_size, &ivk)
.expect("scanning block for the ZECpages viewing key should work"); .expect("scanning block for the ZECpages viewing key should work");
transactions_found += res.transactions().len(); transactions_found += res.transactions().len();