Factor out `get_commitment_tree` from scan.

This commit is contained in:
Kris Nuttycombe 2020-08-06 18:13:24 -06:00
parent d16c74725e
commit 56e6091876
4 changed files with 72 additions and 53 deletions

View File

@ -1,9 +1,9 @@
use zcash_primitives::{
block::BlockHash,
consensus::{self, BlockHeight},
merkle_tree::CommitmentTree,
primitives::PaymentAddress,
//merkle_tree::{CommitmentTree, IncrementalWitness},
//sapling::Node,
sapling::Node,
transaction::components::Amount,
zip32::ExtendedFullViewingKey,
};
@ -66,8 +66,11 @@ pub trait DBOps {
params: &P,
) -> Result<Vec<ExtendedFullViewingKey>, Self::Error>;
// fn get_commitment_tree(block_height: BlockHeight) -> Result<Option<CommitmentTree<Node>>, Self::Error>;
//
fn get_commitment_tree(
&self,
block_height: BlockHeight,
) -> Result<Option<CommitmentTree<Node>>, Self::Error>;
// fn get_witnesses(block_height: BlockHeight) -> Result<Box<dyn Iterator<Item = IncrementalWitness<Node>>>, Self::Error>;
//
// fn get_nullifiers() -> Result<(Vec<u8>, Account), Self::Error>;

View File

@ -30,7 +30,9 @@ use std::path::Path;
use zcash_primitives::{
block::BlockHash,
consensus::{self, BlockHeight},
merkle_tree::CommitmentTree,
primitives::PaymentAddress,
sapling::Node,
transaction::components::Amount,
zip32::ExtendedFullViewingKey,
};
@ -133,6 +135,13 @@ impl DBOps for DataConnection {
) -> Result<Vec<ExtendedFullViewingKey>, Self::Error> {
query::get_extended_full_viewing_keys(self, params)
}
fn get_commitment_tree(
&self,
block_height: BlockHeight,
) -> Result<Option<CommitmentTree<Node>>, Self::Error> {
query::get_commitment_tree(self, block_height)
}
}
pub struct CacheConnection(Connection);

View File

@ -1,11 +1,13 @@
//! Functions for querying information in the data database.
use rusqlite::NO_PARAMS;
use rusqlite::{OptionalExtension, NO_PARAMS};
use zcash_primitives::{
consensus::{self},
consensus::{self, BlockHeight},
merkle_tree::CommitmentTree,
note_encryption::Memo,
primitives::PaymentAddress,
sapling::Node,
transaction::components::Amount,
zip32::ExtendedFullViewingKey,
};
@ -236,6 +238,29 @@ pub fn get_extended_full_viewing_keys<P: consensus::Parameters>(
rows.collect::<Result<Result<_, _>, _>>()?
}
pub fn get_commitment_tree(
data: &DataConnection,
block_height: BlockHeight,
) -> Result<Option<CommitmentTree<Node>>, SqliteClientError> {
data.0
.query_row_and_then(
"SELECT sapling_tree FROM blocks WHERE height = ?",
&[u32::from(block_height)],
|row| {
let row_data: Vec<u8> = row.get(0)?;
CommitmentTree::read(&row_data[..]).map_err(|e| {
rusqlite::Error::FromSqlConversionFailure(
row_data.len(),
rusqlite::types::Type::Blob,
Box::new(e),
)
})
},
)
.optional()
.map_err(SqliteClientError::from)
}
#[cfg(test)]
mod tests {
use rusqlite::Connection;

View File

@ -7,7 +7,10 @@ use rusqlite::{types::ToSql, OptionalExtension, NO_PARAMS};
use zcash_client_backend::{
address::RecipientAddress,
data_api::error::{ChainInvalid, Error},
data_api::{
error::{ChainInvalid, Error},
DBOps,
},
decrypt_transaction,
encoding::decode_extended_full_viewing_key,
proto::compact_formats::CompactBlock,
@ -88,56 +91,18 @@ pub fn scan_cached_blocks<P: consensus::Parameters>(
// Recall where we synced up to previously.
// If we have never synced, use sapling activation height to select all cached CompactBlocks.
let mut last_height: BlockHeight =
data.0
.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| {
row.get::<_, u32>(0)
.map(BlockHeight::from)
.or(Ok(sapling_activation_height - 1))
})?;
// Fetch the CompactBlocks we need to scan
let mut stmt_blocks = cache.0.prepare(
"SELECT height, data FROM compactblocks WHERE height > ? ORDER BY height ASC LIMIT ?",
)?;
let rows = stmt_blocks.query_map(
&[u32::from(last_height), limit.unwrap_or(u32::max_value())],
|row| {
Ok(CompactBlockRow {
height: row.get::<_, u32>(0).map(BlockHeight::from)?,
data: row.get(1)?,
})
},
)?;
// Fetch the ExtendedFullViewingKeys we are tracking
let mut stmt_fetch_accounts = data
.0
.prepare("SELECT extfvk FROM accounts ORDER BY account ASC")?;
let extfvks = stmt_fetch_accounts.query_map(NO_PARAMS, |row| {
row.get(0).map(|extfvk: String| {
decode_extended_full_viewing_key(
params.hrp_sapling_extended_full_viewing_key(),
&extfvk,
)
})
let mut last_height = data.block_height_extrema().map(|opt| {
opt.map(|(_, max)| max)
.unwrap_or(sapling_activation_height - 1)
})?;
// Raise SQL errors from the query, IO errors from parsing, and incorrect HRP errors.
let extfvks: Vec<_> = extfvks
.collect::<Result<Result<Option<_>, _>, _>>()??
.ok_or(Error::IncorrectHRPExtFVK)?;
let extfvks = data.get_extended_full_viewing_keys(params)?;
// Get the most recent CommitmentTree
let mut stmt_fetch_tree = data
.0
.prepare("SELECT sapling_tree FROM blocks WHERE height = ?")?;
let mut tree = stmt_fetch_tree
.query_row(&[u32::from(last_height)], |row| {
row.get(0).map(|data: Vec<_>| {
CommitmentTree::read(&data[..]).unwrap_or_else(|_| CommitmentTree::new())
})
})
.unwrap_or_else(|_| CommitmentTree::new());
let mut tree = data
.get_commitment_tree(last_height)
.map(|t| t.unwrap_or(CommitmentTree::new()))?;
// Get most recent incremental witnesses for the notes we are tracking
let mut stmt_fetch_witnesses = data
@ -206,6 +171,23 @@ pub fn scan_cached_blocks<P: consensus::Parameters>(
)",
)?;
// Fetch the CompactBlocks we need to scan
let mut stmt_blocks = cache.0.prepare(
"SELECT height, data FROM compactblocks WHERE height > ? ORDER BY height ASC LIMIT ?",
)?;
let rows = stmt_blocks.query_map(
&[
u32::from(last_height).to_sql()?,
limit.unwrap_or(u32::max_value()).to_sql()?,
],
|row| {
Ok(CompactBlockRow {
height: BlockHeight::from_u32(row.get(0)?),
data: row.get(1)?,
})
},
)?;
for row in rows {
let row = row?;