Skip to content

Commit

Permalink
Do not delete sent note data in rewind.
Browse files Browse the repository at this point in the history
  • Loading branch information
nuttycom committed Feb 2, 2022
1 parent 1507d1d commit 488d13f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 19 deletions.
5 changes: 5 additions & 0 deletions zcash_client_sqlite/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ and this library adheres to Rust's notion of
method to be used in contexts where a transaction has just been
constructed, rather than only in the case that a transaction has
been decrypted after being retrieved from the network.
- A new non-null column, `output_pool` has been added to the `sent_notes`
table to enable distinguising between Sapling and transparent outputs
(and in the future, outputs to other pools). This will require a migration,
which may need to be performed in multiple steps. Values for this column
should be assigned by inference from the address type in the stored data.

### Deprecated
- A number of public API methods that are used internally to support the
Expand Down
6 changes: 3 additions & 3 deletions zcash_client_sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,11 @@ impl<P: consensus::Parameters> WalletDb<P> {
stmt_update_sent_note: self.conn.prepare(
"UPDATE sent_notes
SET from_account = ?, address = ?, value = ?, memo = ?
WHERE tx = ? AND output_index = ?",
WHERE tx = ? AND output_pool = ? AND output_index = ?",
)?,
stmt_insert_sent_note: self.conn.prepare(
"INSERT INTO sent_notes (tx, output_index, from_account, address, value, memo)
VALUES (?, ?, ?, ?, ?, ?)",
"INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
VALUES (?, ?, ?, ?, ?, ?, ?)",
)?,
stmt_insert_witness: self.conn.prepare(
"INSERT INTO sapling_witnesses (note, block, witness)
Expand Down
42 changes: 27 additions & 15 deletions zcash_client_sqlite/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ use {
pub mod init;
pub mod transact;

enum PoolType {
Transparent,
Sapling,
}

impl PoolType {
fn typecode(&self) -> i64 {
// These constants are *incidentally* shared with the typecodes
// for unified addresses, but this is exclusively an internal
// implementation detail.
match self {
PoolType::Transparent => 0i64,
PoolType::Sapling => 2i64,
}
}
}

/// This trait provides a generalization over shielded output representations.
#[deprecated(note = "This trait will be removed in a future release.")]
pub trait ShieldedOutput {
Expand Down Expand Up @@ -580,18 +597,9 @@ pub(crate) fn rewind_to_height<P: consensus::Parameters>(
&[u32::from(block_height)],
)?;

// Rewind sent notes
wdb.conn.execute(
"DELETE FROM sent_notes
WHERE id_note IN (
SELECT sn.id_note
FROM sent_notes sn
LEFT OUTER JOIN transactions tx
ON tx.id_tx = sn.tx
WHERE tx.block IS NOT NULL AND tx.block > ?
);",
&[u32::from(block_height)],
)?;
// Do not delete sent notes; this can contain data that is not recoverable
// from the chain. Wallets must continue to operate correctly in the
// presence of stale sent notes that link to unmined transactions.

// Rewind utxos
wdb.conn.execute(
Expand Down Expand Up @@ -1096,7 +1104,8 @@ pub fn put_sent_note<'a, P: consensus::Parameters>(
ivalue,
&memo.map(|m| m.as_slice()),
tx_ref,
output_index as i64
PoolType::Sapling.typecode(),
output_index as i64,
])? == 0
{
// It isn't there, so insert.
Expand Down Expand Up @@ -1130,7 +1139,8 @@ pub fn put_sent_utxo<'a, P: consensus::Parameters>(
ivalue,
(None::<&[u8]>),
tx_ref,
output_index as i64
PoolType::Transparent.typecode(),
output_index as i64,
])? == 0
{
// It isn't there, so insert.
Expand Down Expand Up @@ -1164,6 +1174,7 @@ pub fn insert_sent_note<'a, P: consensus::Parameters>(
let ivalue: i64 = value.into();
stmts.stmt_insert_sent_note.execute(params![
tx_ref,
PoolType::Sapling.typecode(),
(output_index as i64),
account.0,
to_str,
Expand Down Expand Up @@ -1192,11 +1203,12 @@ pub fn insert_sent_utxo<'a, P: consensus::Parameters>(
let ivalue: i64 = value.into();
stmts.stmt_insert_sent_note.execute(params![
tx_ref,
PoolType::Transparent.typecode(),
(output_index as i64),
account.0,
to_str,
ivalue,
(None::<&[u8]>)
(None::<&[u8]>),
])?;

Ok(())
Expand Down
3 changes: 2 additions & 1 deletion zcash_client_sqlite/src/wallet/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,15 @@ pub fn init_wallet_db<P>(wdb: &WalletDb<P>) -> Result<(), rusqlite::Error> {
"CREATE TABLE IF NOT EXISTS sent_notes (
id_note INTEGER PRIMARY KEY,
tx INTEGER NOT NULL,
output_pool INTEGER NOT NULL,
output_index INTEGER NOT NULL,
from_account INTEGER NOT NULL,
address TEXT NOT NULL,
value INTEGER NOT NULL,
memo BLOB,
FOREIGN KEY (tx) REFERENCES transactions(id_tx),
FOREIGN KEY (from_account) REFERENCES accounts(account),
CONSTRAINT tx_output UNIQUE (tx, output_index)
CONSTRAINT tx_output UNIQUE (tx, output_pool, output_index)
)",
NO_PARAMS,
)?;
Expand Down

0 comments on commit 488d13f

Please sign in to comment.