zcash_client_sqlite: Add an internal newtype for transaction primary key values.
This commit is contained in:
parent
7f7b685b99
commit
301e8b497c
|
@ -177,11 +177,14 @@ impl fmt::Display for ReceivedNoteId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A newtype wrapper for sqlite primary key values for the utxos
|
/// A newtype wrapper for sqlite primary key values for the utxos table.
|
||||||
/// table.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct UtxoId(pub i64);
|
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.
|
/// A wrapper for the SQLite connection to the wallet database.
|
||||||
pub struct WalletDb<C, P> {
|
pub struct WalletDb<C, P> {
|
||||||
conn: C,
|
conn: C,
|
||||||
|
|
|
@ -108,6 +108,7 @@ use zcash_primitives::{
|
||||||
};
|
};
|
||||||
use zip32::{self, DiversifierIndex, Scope};
|
use zip32::{self, DiversifierIndex, Scope};
|
||||||
|
|
||||||
|
use crate::TxRef;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::SqliteClientError,
|
error::SqliteClientError,
|
||||||
wallet::commitment_tree::{get_max_checkpointed_height, SqliteShardStore},
|
wallet::commitment_tree::{get_max_checkpointed_height, SqliteShardStore},
|
||||||
|
@ -2199,7 +2200,7 @@ pub(crate) fn put_tx_meta(
|
||||||
conn: &rusqlite::Connection,
|
conn: &rusqlite::Connection,
|
||||||
tx: &WalletTx<AccountId>,
|
tx: &WalletTx<AccountId>,
|
||||||
height: BlockHeight,
|
height: BlockHeight,
|
||||||
) -> Result<i64, SqliteClientError> {
|
) -> Result<TxRef, SqliteClientError> {
|
||||||
// It isn't there, so insert our transaction into the database.
|
// It isn't there, so insert our transaction into the database.
|
||||||
let mut stmt_upsert_tx_meta = conn.prepare_cached(
|
let mut stmt_upsert_tx_meta = conn.prepare_cached(
|
||||||
"INSERT INTO transactions (txid, block, mined_height, tx_index)
|
"INSERT INTO transactions (txid, block, mined_height, tx_index)
|
||||||
|
@ -2219,7 +2220,7 @@ pub(crate) fn put_tx_meta(
|
||||||
];
|
];
|
||||||
|
|
||||||
stmt_upsert_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)
|
.map_err(SqliteClientError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,7 +2272,7 @@ pub(crate) fn put_tx_data(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
fee: Option<NonNegativeAmount>,
|
fee: Option<NonNegativeAmount>,
|
||||||
created_at: Option<time::OffsetDateTime>,
|
created_at: Option<time::OffsetDateTime>,
|
||||||
) -> Result<i64, SqliteClientError> {
|
) -> Result<TxRef, SqliteClientError> {
|
||||||
let mut stmt_upsert_tx_data = conn.prepare_cached(
|
let mut stmt_upsert_tx_data = conn.prepare_cached(
|
||||||
"INSERT INTO transactions (txid, created, expiry_height, raw, fee)
|
"INSERT INTO transactions (txid, created, expiry_height, raw, fee)
|
||||||
VALUES (:txid, :created_at, :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
|
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)
|
.map_err(SqliteClientError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2332,7 +2333,7 @@ fn recipient_params<P: consensus::Parameters>(
|
||||||
pub(crate) fn insert_sent_output<P: consensus::Parameters>(
|
pub(crate) fn insert_sent_output<P: consensus::Parameters>(
|
||||||
conn: &rusqlite::Connection,
|
conn: &rusqlite::Connection,
|
||||||
params: &P,
|
params: &P,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
from_account: AccountId,
|
from_account: AccountId,
|
||||||
output: &SentTransactionOutput<AccountId>,
|
output: &SentTransactionOutput<AccountId>,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> 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 (to_address, to_account_id, pool_type) = recipient_params(params, output.recipient());
|
||||||
let sql_args = named_params![
|
let sql_args = named_params![
|
||||||
":tx": &tx_ref,
|
":tx": tx_ref.0,
|
||||||
":output_pool": &pool_code(pool_type),
|
":output_pool": &pool_code(pool_type),
|
||||||
":output_index": &i64::try_from(output.output_index()).unwrap(),
|
":output_index": &i64::try_from(output.output_index()).unwrap(),
|
||||||
":from_account_id": from_account.0,
|
":from_account_id": from_account.0,
|
||||||
|
@ -2378,7 +2379,7 @@ pub(crate) fn put_sent_output<P: consensus::Parameters>(
|
||||||
conn: &rusqlite::Connection,
|
conn: &rusqlite::Connection,
|
||||||
params: &P,
|
params: &P,
|
||||||
from_account: AccountId,
|
from_account: AccountId,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
output_index: usize,
|
output_index: usize,
|
||||||
recipient: &Recipient<AccountId, Note, OutPoint>,
|
recipient: &Recipient<AccountId, Note, OutPoint>,
|
||||||
value: NonNegativeAmount,
|
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 (to_address, to_account_id, pool_type) = recipient_params(params, recipient);
|
||||||
let sql_args = named_params![
|
let sql_args = named_params![
|
||||||
":tx": &tx_ref,
|
":tx": tx_ref.0,
|
||||||
":output_pool": &pool_code(pool_type),
|
":output_pool": &pool_code(pool_type),
|
||||||
":output_index": &i64::try_from(output_index).unwrap(),
|
":output_index": &i64::try_from(output_index).unwrap(),
|
||||||
":from_account_id": from_account.0,
|
":from_account_id": from_account.0,
|
||||||
|
@ -2515,7 +2516,7 @@ pub(crate) fn query_nullifier_map<N: AsRef<[u8]>>(
|
||||||
conn: &rusqlite::Transaction<'_>,
|
conn: &rusqlite::Transaction<'_>,
|
||||||
spend_pool: ShieldedProtocol,
|
spend_pool: ShieldedProtocol,
|
||||||
nf: &N,
|
nf: &N,
|
||||||
) -> Result<Option<i64>, SqliteClientError> {
|
) -> Result<Option<TxRef>, SqliteClientError> {
|
||||||
let mut stmt_select_locator = conn.prepare_cached(
|
let mut stmt_select_locator = conn.prepare_cached(
|
||||||
"SELECT block_height, tx_index, txid
|
"SELECT block_height, tx_index, txid
|
||||||
FROM nullifier_map
|
FROM nullifier_map
|
||||||
|
|
|
@ -516,7 +516,7 @@ mod tests {
|
||||||
// Don't need to bother with sent outputs for this test.
|
// Don't need to bother with sent outputs for this test.
|
||||||
if output.transfer_type() != TransferType::Outgoing {
|
if output.transfer_type() != TransferType::Outgoing {
|
||||||
put_received_note_before_migration(
|
put_received_note_before_migration(
|
||||||
wdb.conn.0, output, tx_ref, None,
|
wdb.conn.0, output, tx_ref.0, None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use zcash_protocol::{
|
||||||
};
|
};
|
||||||
use zip32::Scope;
|
use zip32::Scope;
|
||||||
|
|
||||||
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId};
|
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId, TxRef};
|
||||||
|
|
||||||
use super::{memo_repr, parse_scope, scope_code};
|
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>(
|
pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(
|
||||||
conn: &Transaction,
|
conn: &Transaction,
|
||||||
output: &T,
|
output: &T,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
spent_in: Option<i64>,
|
spent_in: Option<TxRef>,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let mut stmt_upsert_received_note = conn.prepare_cached(
|
let mut stmt_upsert_received_note = conn.prepare_cached(
|
||||||
"INSERT INTO orchard_received_notes
|
"INSERT INTO orchard_received_notes
|
||||||
|
@ -263,7 +263,7 @@ pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(
|
||||||
let diversifier = to.diversifier();
|
let diversifier = to.diversifier();
|
||||||
|
|
||||||
let sql_args = named_params![
|
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"),
|
":action_index": i64::try_from(output.index()).expect("output indices are representable as i64"),
|
||||||
":account_id": output.account_id().0,
|
":account_id": output.account_id().0,
|
||||||
":diversifier": diversifier.as_array(),
|
":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",
|
ON CONFLICT (orchard_received_note_id, transaction_id) DO NOTHING",
|
||||||
named_params![
|
named_params![
|
||||||
":orchard_received_note_id": received_note_id,
|
":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.
|
/// spending transaction has been mined.
|
||||||
pub(crate) fn mark_orchard_note_spent(
|
pub(crate) fn mark_orchard_note_spent(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
nf: &Nullifier,
|
nf: &Nullifier,
|
||||||
) -> Result<bool, SqliteClientError> {
|
) -> Result<bool, SqliteClientError> {
|
||||||
let mut stmt_mark_orchard_note_spent = conn.prepare_cached(
|
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![
|
match stmt_mark_orchard_note_spent.execute(named_params![
|
||||||
":nf": nf.to_bytes(),
|
":nf": nf.to_bytes(),
|
||||||
":transaction_id": tx_ref
|
":transaction_id": tx_ref.0
|
||||||
])? {
|
])? {
|
||||||
0 => Ok(false),
|
0 => Ok(false),
|
||||||
1 => Ok(true),
|
1 => Ok(true),
|
||||||
|
|
|
@ -20,7 +20,7 @@ use zcash_protocol::{
|
||||||
};
|
};
|
||||||
use zip32::Scope;
|
use zip32::Scope;
|
||||||
|
|
||||||
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId};
|
use crate::{error::SqliteClientError, AccountId, ReceivedNoteId, TxRef};
|
||||||
|
|
||||||
use super::{memo_repr, parse_scope, scope_code};
|
use super::{memo_repr, parse_scope, scope_code};
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ pub(crate) fn detect_spending_accounts<'a>(
|
||||||
/// spending transaction has been mined.
|
/// spending transaction has been mined.
|
||||||
pub(crate) fn mark_sapling_note_spent(
|
pub(crate) fn mark_sapling_note_spent(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
nf: &sapling::Nullifier,
|
nf: &sapling::Nullifier,
|
||||||
) -> Result<bool, SqliteClientError> {
|
) -> Result<bool, SqliteClientError> {
|
||||||
let mut stmt_mark_sapling_note_spent = conn.prepare_cached(
|
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![
|
match stmt_mark_sapling_note_spent.execute(named_params![
|
||||||
":nf": &nf.0[..],
|
":nf": &nf.0[..],
|
||||||
":transaction_id": tx_ref
|
":transaction_id": tx_ref.0
|
||||||
])? {
|
])? {
|
||||||
0 => Ok(false),
|
0 => Ok(false),
|
||||||
1 => Ok(true),
|
1 => Ok(true),
|
||||||
|
@ -327,8 +327,8 @@ pub(crate) fn mark_sapling_note_spent(
|
||||||
pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
|
pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
|
||||||
conn: &Transaction,
|
conn: &Transaction,
|
||||||
output: &T,
|
output: &T,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
spent_in: Option<i64>,
|
spent_in: Option<TxRef>,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let mut stmt_upsert_received_note = conn.prepare_cached(
|
let mut stmt_upsert_received_note = conn.prepare_cached(
|
||||||
"INSERT INTO sapling_received_notes
|
"INSERT INTO sapling_received_notes
|
||||||
|
@ -366,7 +366,7 @@ pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
|
||||||
let diversifier = to.diversifier();
|
let diversifier = to.diversifier();
|
||||||
|
|
||||||
let sql_args = named_params![
|
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"),
|
":output_index": i64::try_from(output.index()).expect("output indices are representable as i64"),
|
||||||
":account_id": output.account_id().0,
|
":account_id": output.account_id().0,
|
||||||
":diversifier": &diversifier.0.as_ref(),
|
":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",
|
ON CONFLICT (sapling_received_note_id, transaction_id) DO NOTHING",
|
||||||
named_params![
|
named_params![
|
||||||
":sapling_received_note_id": received_note_id,
|
":sapling_received_note_id": received_note_id,
|
||||||
":transaction_id": spent_in
|
":transaction_id": spent_in.0
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use zcash_primitives::{
|
||||||
};
|
};
|
||||||
use zcash_protocol::consensus::{self, BlockHeight};
|
use zcash_protocol::consensus::{self, BlockHeight};
|
||||||
|
|
||||||
|
use crate::TxRef;
|
||||||
use crate::{error::SqliteClientError, AccountId, UtxoId};
|
use crate::{error::SqliteClientError, AccountId, UtxoId};
|
||||||
|
|
||||||
use super::{chain_tip_height, get_account_ids};
|
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.
|
/// Marks the given UTXO as having been spent.
|
||||||
pub(crate) fn mark_transparent_utxo_spent(
|
pub(crate) fn mark_transparent_utxo_spent(
|
||||||
conn: &rusqlite::Connection,
|
conn: &rusqlite::Connection,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
outpoint: &OutPoint,
|
outpoint: &OutPoint,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let mut stmt_mark_transparent_utxo_spent = conn.prepare_cached(
|
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![
|
let sql_args = named_params![
|
||||||
":spent_in_tx": &tx_ref,
|
":spent_in_tx": tx_ref.0,
|
||||||
":prevout_txid": &outpoint.hash().to_vec(),
|
":prevout_txid": &outpoint.hash().to_vec(),
|
||||||
":prevout_idx": &outpoint.n(),
|
":prevout_idx": &outpoint.n(),
|
||||||
];
|
];
|
||||||
|
|
|
@ -15,6 +15,7 @@ use zcash_primitives::{
|
||||||
};
|
};
|
||||||
use zcash_protocol::consensus;
|
use zcash_protocol::consensus;
|
||||||
|
|
||||||
|
use crate::TxRef;
|
||||||
use crate::{
|
use crate::{
|
||||||
error::SqliteClientError,
|
error::SqliteClientError,
|
||||||
wallet::{get_account, GAP_LIMIT},
|
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>(
|
pub(crate) fn mark_ephemeral_address_as_used<P: consensus::Parameters>(
|
||||||
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
|
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
|
||||||
ephemeral_address: &TransparentAddress,
|
ephemeral_address: &TransparentAddress,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let address_str = ephemeral_address.encode(&wdb.params);
|
let address_str = ephemeral_address.encode(&wdb.params);
|
||||||
ephemeral_address_reuse_check(wdb, &address_str)?;
|
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
|
SET used_in_tx = :tx_ref, seen_in_tx = :tx_ref
|
||||||
WHERE address = :address
|
WHERE address = :address
|
||||||
RETURNING account_id, address_index",
|
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)?)),
|
|row| Ok((AccountId(row.get::<_, u32>(0)?), row.get::<_, u32>(1)?)),
|
||||||
)
|
)
|
||||||
.optional()?;
|
.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>(
|
pub(crate) fn mark_ephemeral_address_as_seen<P: consensus::Parameters>(
|
||||||
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
|
wdb: &mut WalletDb<SqlTransaction<'_>, P>,
|
||||||
address: &TransparentAddress,
|
address: &TransparentAddress,
|
||||||
tx_ref: i64,
|
tx_ref: TxRef,
|
||||||
) -> Result<(), SqliteClientError> {
|
) -> Result<(), SqliteClientError> {
|
||||||
let address_str = address.encode(&wdb.params);
|
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,
|
tx_index ASC NULLS LAST,
|
||||||
e.seen_in_tx ASC NULLS LAST
|
e.seen_in_tx ASC NULLS LAST
|
||||||
LIMIT 1",
|
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),
|
|row| row.get::<_, i64>(0),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue