zcash_client_sqlite: Add an internal newtype for transaction primary key values.

This commit is contained in:
Kris Nuttycombe 2024-07-29 11:41:56 -06:00
parent 7f7b685b99
commit 301e8b497c
7 changed files with 39 additions and 33 deletions

View File

@ -177,11 +177,14 @@ impl fmt::Display for ReceivedNoteId {
}
}
/// A newtype wrapper for sqlite primary key values for the utxos
/// table.
/// A newtype wrapper for sqlite primary key values for the utxos table.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct UtxoId(pub i64);
/// A newtype wrapper for sqlite primary key values for the transactions table.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct TxRef(pub i64);
/// A wrapper for the SQLite connection to the wallet database.
pub struct WalletDb<C, P> {
conn: C,

View File

@ -108,6 +108,7 @@ use zcash_primitives::{
};
use zip32::{self, DiversifierIndex, Scope};
use crate::TxRef;
use crate::{
error::SqliteClientError,
wallet::commitment_tree::{get_max_checkpointed_height, SqliteShardStore},
@ -2199,7 +2200,7 @@ pub(crate) fn put_tx_meta(
conn: &rusqlite::Connection,
tx: &WalletTx<AccountId>,
height: BlockHeight,
) -> Result<i64, SqliteClientError> {
) -> Result<TxRef, SqliteClientError> {
// It isn't there, so insert our transaction into the database.
let mut stmt_upsert_tx_meta = conn.prepare_cached(
"INSERT INTO transactions (txid, block, mined_height, tx_index)
@ -2219,7 +2220,7 @@ pub(crate) fn put_tx_meta(
];
stmt_upsert_tx_meta
.query_row(tx_params, |row| row.get::<_, i64>(0))
.query_row(tx_params, |row| row.get::<_, i64>(0).map(TxRef))
.map_err(SqliteClientError::from)
}
@ -2271,7 +2272,7 @@ pub(crate) fn put_tx_data(
tx: &Transaction,
fee: Option<NonNegativeAmount>,
created_at: Option<time::OffsetDateTime>,
) -> Result<i64, SqliteClientError> {
) -> Result<TxRef, SqliteClientError> {
let mut stmt_upsert_tx_data = conn.prepare_cached(
"INSERT INTO transactions (txid, created, expiry_height, raw, fee)
VALUES (:txid, :created_at, :expiry_height, :raw, :fee)
@ -2295,7 +2296,7 @@ pub(crate) fn put_tx_data(
];
stmt_upsert_tx_data
.query_row(tx_params, |row| row.get::<_, i64>(0))
.query_row(tx_params, |row| row.get::<_, i64>(0).map(TxRef))
.map_err(SqliteClientError::from)
}
@ -2332,7 +2333,7 @@ fn recipient_params<P: consensus::Parameters>(
pub(crate) fn insert_sent_output<P: consensus::Parameters>(
conn: &rusqlite::Connection,
params: &P,
tx_ref: i64,
tx_ref: TxRef,
from_account: AccountId,
output: &SentTransactionOutput<AccountId>,
) -> Result<(), SqliteClientError> {
@ -2347,7 +2348,7 @@ pub(crate) fn insert_sent_output<P: consensus::Parameters>(
let (to_address, to_account_id, pool_type) = recipient_params(params, output.recipient());
let sql_args = named_params![
":tx": &tx_ref,
":tx": tx_ref.0,
":output_pool": &pool_code(pool_type),
":output_index": &i64::try_from(output.output_index()).unwrap(),
":from_account_id": from_account.0,
@ -2378,7 +2379,7 @@ pub(crate) fn put_sent_output<P: consensus::Parameters>(
conn: &rusqlite::Connection,
params: &P,
from_account: AccountId,
tx_ref: i64,
tx_ref: TxRef,
output_index: usize,
recipient: &Recipient<AccountId, Note, OutPoint>,
value: NonNegativeAmount,
@ -2401,7 +2402,7 @@ pub(crate) fn put_sent_output<P: consensus::Parameters>(
let (to_address, to_account_id, pool_type) = recipient_params(params, recipient);
let sql_args = named_params![
":tx": &tx_ref,
":tx": tx_ref.0,
":output_pool": &pool_code(pool_type),
":output_index": &i64::try_from(output_index).unwrap(),
":from_account_id": from_account.0,
@ -2515,7 +2516,7 @@ pub(crate) fn query_nullifier_map<N: AsRef<[u8]>>(
conn: &rusqlite::Transaction<'_>,
spend_pool: ShieldedProtocol,
nf: &N,
) -> Result<Option<i64>, SqliteClientError> {
) -> Result<Option<TxRef>, SqliteClientError> {
let mut stmt_select_locator = conn.prepare_cached(
"SELECT block_height, tx_index, txid
FROM nullifier_map

View File

@ -516,7 +516,7 @@ mod tests {
// Don't need to bother with sent outputs for this test.
if output.transfer_type() != TransferType::Outgoing {
put_received_note_before_migration(
wdb.conn.0, output, tx_ref, None,
wdb.conn.0, output, tx_ref.0, None,
)
.unwrap();
}
@ -529,7 +529,7 @@ mod tests {
}
}
put_received_note_before_migration(wdb.conn.0, output, tx_ref, None)
put_received_note_before_migration(wdb.conn.0, output, tx_ref.0, None)
.unwrap();
}
}

View File

@ -21,7 +21,7 @@ use zcash_protocol::{
};
use zip32::Scope;
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId};
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId, TxRef};
use super::{memo_repr, parse_scope, scope_code};
@ -227,8 +227,8 @@ pub(crate) fn select_spendable_orchard_notes<P: consensus::Parameters>(
pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(
conn: &Transaction,
output: &T,
tx_ref: i64,
spent_in: Option<i64>,
tx_ref: TxRef,
spent_in: Option<TxRef>,
) -> Result<(), SqliteClientError> {
let mut stmt_upsert_received_note = conn.prepare_cached(
"INSERT INTO orchard_received_notes
@ -263,7 +263,7 @@ pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(
let diversifier = to.diversifier();
let sql_args = named_params![
":tx": &tx_ref,
":tx": tx_ref.0,
":action_index": i64::try_from(output.index()).expect("output indices are representable as i64"),
":account_id": output.account_id().0,
":diversifier": diversifier.as_array(),
@ -288,7 +288,7 @@ pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(
ON CONFLICT (orchard_received_note_id, transaction_id) DO NOTHING",
named_params![
":orchard_received_note_id": received_note_id,
":transaction_id": spent_in
":transaction_id": spent_in.0
],
)?;
}
@ -366,7 +366,7 @@ pub(crate) fn detect_spending_accounts<'a>(
/// spending transaction has been mined.
pub(crate) fn mark_orchard_note_spent(
conn: &Connection,
tx_ref: i64,
tx_ref: TxRef,
nf: &Nullifier,
) -> Result<bool, SqliteClientError> {
let mut stmt_mark_orchard_note_spent = conn.prepare_cached(
@ -377,7 +377,7 @@ pub(crate) fn mark_orchard_note_spent(
match stmt_mark_orchard_note_spent.execute(named_params![
":nf": nf.to_bytes(),
":transaction_id": tx_ref
":transaction_id": tx_ref.0
])? {
0 => Ok(false),
1 => Ok(true),

View File

@ -20,7 +20,7 @@ use zcash_protocol::{
};
use zip32::Scope;
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId};
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId, TxRef};
use super::{memo_repr, parse_scope, scope_code};
@ -300,7 +300,7 @@ pub(crate) fn detect_spending_accounts<'a>(
/// spending transaction has been mined.
pub(crate) fn mark_sapling_note_spent(
conn: &Connection,
tx_ref: i64,
tx_ref: TxRef,
nf: &sapling::Nullifier,
) -> Result<bool, SqliteClientError> {
let mut stmt_mark_sapling_note_spent = conn.prepare_cached(
@ -311,7 +311,7 @@ pub(crate) fn mark_sapling_note_spent(
match stmt_mark_sapling_note_spent.execute(named_params![
":nf": &nf.0[..],
":transaction_id": tx_ref
":transaction_id": tx_ref.0
])? {
0 => Ok(false),
1 => Ok(true),
@ -327,8 +327,8 @@ pub(crate) fn mark_sapling_note_spent(
pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
conn: &Transaction,
output: &T,
tx_ref: i64,
spent_in: Option<i64>,
tx_ref: TxRef,
spent_in: Option<TxRef>,
) -> Result<(), SqliteClientError> {
let mut stmt_upsert_received_note = conn.prepare_cached(
"INSERT INTO sapling_received_notes
@ -366,7 +366,7 @@ pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
let diversifier = to.diversifier();
let sql_args = named_params![
":tx": &tx_ref,
":tx": tx_ref.0,
":output_index": i64::try_from(output.index()).expect("output indices are representable as i64"),
":account_id": output.account_id().0,
":diversifier": &diversifier.0.as_ref(),
@ -390,7 +390,7 @@ pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
ON CONFLICT (sapling_received_note_id, transaction_id) DO NOTHING",
named_params![
":sapling_received_note_id": received_note_id,
":transaction_id": spent_in
":transaction_id": spent_in.0
],
)?;
}

View File

@ -20,6 +20,7 @@ use zcash_primitives::{
};
use zcash_protocol::consensus::{self, BlockHeight};
use crate::TxRef;
use crate::{error::SqliteClientError, AccountId, UtxoId};
use super::{chain_tip_height, get_account_ids};
@ -429,7 +430,7 @@ pub(crate) fn add_transparent_account_balances(
/// Marks the given UTXO as having been spent.
pub(crate) fn mark_transparent_utxo_spent(
conn: &rusqlite::Connection,
tx_ref: i64,
tx_ref: TxRef,
outpoint: &OutPoint,
) -> Result<(), SqliteClientError> {
let mut stmt_mark_transparent_utxo_spent = conn.prepare_cached(
@ -443,7 +444,7 @@ pub(crate) fn mark_transparent_utxo_spent(
)?;
let sql_args = named_params![
":spent_in_tx": &tx_ref,
":spent_in_tx": tx_ref.0,
":prevout_txid": &outpoint.hash().to_vec(),
":prevout_idx": &outpoint.n(),
];

View File

@ -15,6 +15,7 @@ use zcash_primitives::{
};
use zcash_protocol::consensus;
use crate::TxRef;
use crate::{
error::SqliteClientError,
wallet::{get_account, GAP_LIMIT},
@ -360,7 +361,7 @@ fn ephemeral_address_reuse_check<P: consensus::Parameters>(
pub(crate) fn mark_ephemeral_address_as_used<P: consensus::Parameters>(
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
ephemeral_address: &TransparentAddress,
tx_ref: i64,
tx_ref: TxRef,
) -> Result<(), SqliteClientError> {
let address_str = ephemeral_address.encode(&wdb.params);
ephemeral_address_reuse_check(wdb, &address_str)?;
@ -377,7 +378,7 @@ pub(crate) fn mark_ephemeral_address_as_used<P: consensus::Parameters>(
SET used_in_tx = :tx_ref, seen_in_tx = :tx_ref
WHERE address = :address
RETURNING account_id, address_index",
named_params![":tx_ref": &tx_ref, ":address": address_str],
named_params![":tx_ref": tx_ref.0, ":address": address_str],
|row| Ok((AccountId(row.get::<_, u32>(0)?), row.get::<_, u32>(1)?)),
)
.optional()?;
@ -398,7 +399,7 @@ pub(crate) fn mark_ephemeral_address_as_used<P: consensus::Parameters>(
pub(crate) fn mark_ephemeral_address_as_seen<P: consensus::Parameters>(
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
address: &TransparentAddress,
tx_ref: i64,
tx_ref: TxRef,
) -> Result<(), SqliteClientError> {
let address_str = address.encode(&wdb.params);
@ -419,7 +420,7 @@ pub(crate) fn mark_ephemeral_address_as_seen<P: consensus::Parameters>(
tx_index ASC NULLS LAST,
e.seen_in_tx ASC NULLS LAST
LIMIT 1",
named_params![":tx_ref": &tx_ref, ":address": address_str],
named_params![":tx_ref": tx_ref.0, ":address": address_str],
|row| row.get::<_, i64>(0),
)?;