zcash_client_sqlite: Move `DataConnStmtCache` into submodule
This removes direct access to the prepared statements, instead forcing callers to use the type-safe methods added in the previous commit.
This commit is contained in:
parent
12e8c53310
commit
04b1d505b2
|
@ -36,7 +36,7 @@ use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rusqlite::{Connection, Statement, NO_PARAMS};
|
use rusqlite::{Connection, NO_PARAMS};
|
||||||
|
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
|
@ -70,6 +70,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
mod prepared;
|
mod prepared;
|
||||||
|
pub use prepared::DataConnStmtCache;
|
||||||
|
|
||||||
pub mod chain;
|
pub mod chain;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -243,135 +244,6 @@ impl<P: consensus::Parameters> WalletReadTransparent for WalletDb<P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary type used to implement [`WalletWrite`] for the SQLite database.
|
|
||||||
///
|
|
||||||
/// A data structure that stores the SQLite prepared statements that are
|
|
||||||
/// required for the implementation of [`WalletWrite`] against the backing
|
|
||||||
/// store.
|
|
||||||
///
|
|
||||||
/// [`WalletWrite`]: zcash_client_backend::data_api::WalletWrite
|
|
||||||
pub struct DataConnStmtCache<'a, P> {
|
|
||||||
wallet_db: &'a WalletDb<P>,
|
|
||||||
stmt_insert_block: Statement<'a>,
|
|
||||||
|
|
||||||
stmt_insert_tx_meta: Statement<'a>,
|
|
||||||
stmt_update_tx_meta: Statement<'a>,
|
|
||||||
|
|
||||||
stmt_insert_tx_data: Statement<'a>,
|
|
||||||
stmt_update_tx_data: Statement<'a>,
|
|
||||||
stmt_select_tx_ref: Statement<'a>,
|
|
||||||
|
|
||||||
stmt_mark_sapling_note_spent: Statement<'a>,
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_mark_transparent_utxo_spent: Statement<'a>,
|
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_insert_received_transparent_utxo: Statement<'a>,
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_delete_utxos: Statement<'a>,
|
|
||||||
stmt_insert_received_note: Statement<'a>,
|
|
||||||
stmt_update_received_note: Statement<'a>,
|
|
||||||
stmt_select_received_note: Statement<'a>,
|
|
||||||
|
|
||||||
stmt_insert_sent_note: Statement<'a>,
|
|
||||||
stmt_update_sent_note: Statement<'a>,
|
|
||||||
|
|
||||||
stmt_insert_witness: Statement<'a>,
|
|
||||||
stmt_prune_witnesses: Statement<'a>,
|
|
||||||
stmt_update_expired: Statement<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, P> DataConnStmtCache<'a, P> {
|
|
||||||
fn new(wallet_db: &'a WalletDb<P>) -> Result<Self, SqliteClientError> {
|
|
||||||
Ok(
|
|
||||||
DataConnStmtCache {
|
|
||||||
wallet_db,
|
|
||||||
stmt_insert_block: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO blocks (height, hash, time, sapling_tree)
|
|
||||||
VALUES (?, ?, ?, ?)",
|
|
||||||
)?,
|
|
||||||
stmt_insert_tx_meta: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO transactions (txid, block, tx_index)
|
|
||||||
VALUES (?, ?, ?)",
|
|
||||||
)?,
|
|
||||||
stmt_update_tx_meta: wallet_db.conn.prepare(
|
|
||||||
"UPDATE transactions
|
|
||||||
SET block = ?, tx_index = ? WHERE txid = ?",
|
|
||||||
)?,
|
|
||||||
stmt_insert_tx_data: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO transactions (txid, created, expiry_height, raw)
|
|
||||||
VALUES (?, ?, ?, ?)",
|
|
||||||
)?,
|
|
||||||
stmt_update_tx_data: wallet_db.conn.prepare(
|
|
||||||
"UPDATE transactions
|
|
||||||
SET expiry_height = ?, raw = ? WHERE txid = ?",
|
|
||||||
)?,
|
|
||||||
stmt_select_tx_ref: wallet_db.conn.prepare(
|
|
||||||
"SELECT id_tx FROM transactions WHERE txid = ?",
|
|
||||||
)?,
|
|
||||||
stmt_mark_sapling_note_spent: wallet_db.conn.prepare(
|
|
||||||
"UPDATE received_notes SET spent = ? WHERE nf = ?"
|
|
||||||
)?,
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_mark_transparent_utxo_spent: wallet_db.conn.prepare(
|
|
||||||
"UPDATE utxos SET spent_in_tx = :spent_in_tx
|
|
||||||
WHERE prevout_txid = :prevout_txid
|
|
||||||
AND prevout_idx = :prevout_idx"
|
|
||||||
)?,
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_insert_received_transparent_utxo: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO utxos (address, prevout_txid, prevout_idx, script, value_zat, height)
|
|
||||||
VALUES (:address, :prevout_txid, :prevout_idx, :script, :value_zat, :height)"
|
|
||||||
)?,
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
|
||||||
stmt_delete_utxos: wallet_db.conn.prepare(
|
|
||||||
"DELETE FROM utxos WHERE address = :address AND height > :above_height"
|
|
||||||
)?,
|
|
||||||
stmt_insert_received_note: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO received_notes (tx, output_index, account, diversifier, value, rcm, memo, nf, is_change)
|
|
||||||
VALUES (:tx, :output_index, :account, :diversifier, :value, :rcm, :memo, :nf, :is_change)",
|
|
||||||
)?,
|
|
||||||
stmt_update_received_note: wallet_db.conn.prepare(
|
|
||||||
"UPDATE received_notes
|
|
||||||
SET account = :account,
|
|
||||||
diversifier = :diversifier,
|
|
||||||
value = :value,
|
|
||||||
rcm = :rcm,
|
|
||||||
nf = IFNULL(:nf, nf),
|
|
||||||
memo = IFNULL(:memo, memo),
|
|
||||||
is_change = IFNULL(:is_change, is_change)
|
|
||||||
WHERE tx = :tx AND output_index = :output_index",
|
|
||||||
)?,
|
|
||||||
stmt_select_received_note: wallet_db.conn.prepare(
|
|
||||||
"SELECT id_note FROM received_notes WHERE tx = ? AND output_index = ?"
|
|
||||||
)?,
|
|
||||||
stmt_update_sent_note: wallet_db.conn.prepare(
|
|
||||||
"UPDATE sent_notes
|
|
||||||
SET from_account = ?, address = ?, value = ?, memo = ?
|
|
||||||
WHERE tx = ? AND output_pool = ? AND output_index = ?",
|
|
||||||
)?,
|
|
||||||
stmt_insert_sent_note: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
||||||
)?,
|
|
||||||
stmt_insert_witness: wallet_db.conn.prepare(
|
|
||||||
"INSERT INTO sapling_witnesses (note, block, witness)
|
|
||||||
VALUES (?, ?, ?)",
|
|
||||||
)?,
|
|
||||||
stmt_prune_witnesses: wallet_db.conn.prepare(
|
|
||||||
"DELETE FROM sapling_witnesses WHERE block < ?"
|
|
||||||
)?,
|
|
||||||
stmt_update_expired: wallet_db.conn.prepare(
|
|
||||||
"UPDATE received_notes SET spent = NULL WHERE EXISTS (
|
|
||||||
SELECT id_tx FROM transactions
|
|
||||||
WHERE id_tx = received_notes.spent AND block IS NULL AND expiry_height < ?
|
|
||||||
)",
|
|
||||||
)?,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
|
impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
|
||||||
type Error = SqliteClientError;
|
type Error = SqliteClientError;
|
||||||
type NoteRef = NoteId;
|
type NoteRef = NoteId;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//! - Build the statement in [`DataConnStmtCache::new`].
|
//! - Build the statement in [`DataConnStmtCache::new`].
|
||||||
//! - Add a crate-private helper method to `DataConnStmtCache` for running the statement.
|
//! - Add a crate-private helper method to `DataConnStmtCache` for running the statement.
|
||||||
|
|
||||||
use rusqlite::{params, ToSql};
|
use rusqlite::{params, Statement, ToSql};
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
block::BlockHash,
|
block::BlockHash,
|
||||||
consensus::{self, BlockHeight},
|
consensus::{self, BlockHeight},
|
||||||
|
@ -18,7 +18,7 @@ use zcash_primitives::{
|
||||||
zip32::AccountId,
|
zip32::AccountId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{error::SqliteClientError, wallet::PoolType, DataConnStmtCache, NoteId};
|
use crate::{error::SqliteClientError, wallet::PoolType, NoteId, WalletDb};
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
use {
|
use {
|
||||||
|
@ -28,7 +28,134 @@ use {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The primary type used to implement [`WalletWrite`] for the SQLite database.
|
||||||
|
///
|
||||||
|
/// A data structure that stores the SQLite prepared statements that are
|
||||||
|
/// required for the implementation of [`WalletWrite`] against the backing
|
||||||
|
/// store.
|
||||||
|
///
|
||||||
|
/// [`WalletWrite`]: zcash_client_backend::data_api::WalletWrite
|
||||||
|
pub struct DataConnStmtCache<'a, P> {
|
||||||
|
pub(crate) wallet_db: &'a WalletDb<P>,
|
||||||
|
stmt_insert_block: Statement<'a>,
|
||||||
|
|
||||||
|
stmt_insert_tx_meta: Statement<'a>,
|
||||||
|
stmt_update_tx_meta: Statement<'a>,
|
||||||
|
|
||||||
|
stmt_insert_tx_data: Statement<'a>,
|
||||||
|
stmt_update_tx_data: Statement<'a>,
|
||||||
|
stmt_select_tx_ref: Statement<'a>,
|
||||||
|
|
||||||
|
stmt_mark_sapling_note_spent: Statement<'a>,
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_mark_transparent_utxo_spent: Statement<'a>,
|
||||||
|
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_insert_received_transparent_utxo: Statement<'a>,
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_delete_utxos: Statement<'a>,
|
||||||
|
stmt_insert_received_note: Statement<'a>,
|
||||||
|
stmt_update_received_note: Statement<'a>,
|
||||||
|
stmt_select_received_note: Statement<'a>,
|
||||||
|
|
||||||
|
stmt_insert_sent_note: Statement<'a>,
|
||||||
|
stmt_update_sent_note: Statement<'a>,
|
||||||
|
|
||||||
|
stmt_insert_witness: Statement<'a>,
|
||||||
|
stmt_prune_witnesses: Statement<'a>,
|
||||||
|
stmt_update_expired: Statement<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, P> DataConnStmtCache<'a, P> {
|
impl<'a, P> DataConnStmtCache<'a, P> {
|
||||||
|
pub(crate) fn new(wallet_db: &'a WalletDb<P>) -> Result<Self, SqliteClientError> {
|
||||||
|
Ok(
|
||||||
|
DataConnStmtCache {
|
||||||
|
wallet_db,
|
||||||
|
stmt_insert_block: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO blocks (height, hash, time, sapling_tree)
|
||||||
|
VALUES (?, ?, ?, ?)",
|
||||||
|
)?,
|
||||||
|
stmt_insert_tx_meta: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO transactions (txid, block, tx_index)
|
||||||
|
VALUES (?, ?, ?)",
|
||||||
|
)?,
|
||||||
|
stmt_update_tx_meta: wallet_db.conn.prepare(
|
||||||
|
"UPDATE transactions
|
||||||
|
SET block = ?, tx_index = ? WHERE txid = ?",
|
||||||
|
)?,
|
||||||
|
stmt_insert_tx_data: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO transactions (txid, created, expiry_height, raw)
|
||||||
|
VALUES (?, ?, ?, ?)",
|
||||||
|
)?,
|
||||||
|
stmt_update_tx_data: wallet_db.conn.prepare(
|
||||||
|
"UPDATE transactions
|
||||||
|
SET expiry_height = ?, raw = ? WHERE txid = ?",
|
||||||
|
)?,
|
||||||
|
stmt_select_tx_ref: wallet_db.conn.prepare(
|
||||||
|
"SELECT id_tx FROM transactions WHERE txid = ?",
|
||||||
|
)?,
|
||||||
|
stmt_mark_sapling_note_spent: wallet_db.conn.prepare(
|
||||||
|
"UPDATE received_notes SET spent = ? WHERE nf = ?"
|
||||||
|
)?,
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_mark_transparent_utxo_spent: wallet_db.conn.prepare(
|
||||||
|
"UPDATE utxos SET spent_in_tx = :spent_in_tx
|
||||||
|
WHERE prevout_txid = :prevout_txid
|
||||||
|
AND prevout_idx = :prevout_idx"
|
||||||
|
)?,
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_insert_received_transparent_utxo: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO utxos (address, prevout_txid, prevout_idx, script, value_zat, height)
|
||||||
|
VALUES (:address, :prevout_txid, :prevout_idx, :script, :value_zat, :height)"
|
||||||
|
)?,
|
||||||
|
#[cfg(feature = "transparent-inputs")]
|
||||||
|
stmt_delete_utxos: wallet_db.conn.prepare(
|
||||||
|
"DELETE FROM utxos WHERE address = :address AND height > :above_height"
|
||||||
|
)?,
|
||||||
|
stmt_insert_received_note: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO received_notes (tx, output_index, account, diversifier, value, rcm, memo, nf, is_change)
|
||||||
|
VALUES (:tx, :output_index, :account, :diversifier, :value, :rcm, :memo, :nf, :is_change)",
|
||||||
|
)?,
|
||||||
|
stmt_update_received_note: wallet_db.conn.prepare(
|
||||||
|
"UPDATE received_notes
|
||||||
|
SET account = :account,
|
||||||
|
diversifier = :diversifier,
|
||||||
|
value = :value,
|
||||||
|
rcm = :rcm,
|
||||||
|
nf = IFNULL(:nf, nf),
|
||||||
|
memo = IFNULL(:memo, memo),
|
||||||
|
is_change = IFNULL(:is_change, is_change)
|
||||||
|
WHERE tx = :tx AND output_index = :output_index",
|
||||||
|
)?,
|
||||||
|
stmt_select_received_note: wallet_db.conn.prepare(
|
||||||
|
"SELECT id_note FROM received_notes WHERE tx = ? AND output_index = ?"
|
||||||
|
)?,
|
||||||
|
stmt_update_sent_note: wallet_db.conn.prepare(
|
||||||
|
"UPDATE sent_notes
|
||||||
|
SET from_account = ?, address = ?, value = ?, memo = ?
|
||||||
|
WHERE tx = ? AND output_pool = ? AND output_index = ?",
|
||||||
|
)?,
|
||||||
|
stmt_insert_sent_note: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
)?,
|
||||||
|
stmt_insert_witness: wallet_db.conn.prepare(
|
||||||
|
"INSERT INTO sapling_witnesses (note, block, witness)
|
||||||
|
VALUES (?, ?, ?)",
|
||||||
|
)?,
|
||||||
|
stmt_prune_witnesses: wallet_db.conn.prepare(
|
||||||
|
"DELETE FROM sapling_witnesses WHERE block < ?"
|
||||||
|
)?,
|
||||||
|
stmt_update_expired: wallet_db.conn.prepare(
|
||||||
|
"UPDATE received_notes SET spent = NULL WHERE EXISTS (
|
||||||
|
SELECT id_tx FROM transactions
|
||||||
|
WHERE id_tx = received_notes.spent AND block IS NULL AND expiry_height < ?
|
||||||
|
)",
|
||||||
|
)?,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Inserts information about a scanned block into the database.
|
/// Inserts information about a scanned block into the database.
|
||||||
pub fn stmt_insert_block(
|
pub fn stmt_insert_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
Loading…
Reference in New Issue