zcash_client_sqlite: Reprocess wallet transactions on upgrade to restore additional transparent history.
This commit is contained in:
parent
c22a2a4c92
commit
484659dddb
|
@ -87,8 +87,8 @@ use {
|
|||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use {
|
||||
zcash_keys::encoding::AddressCodec,
|
||||
zcash_client_backend::wallet::TransparentAddressMetadata,
|
||||
zcash_keys::encoding::AddressCodec,
|
||||
zcash_primitives::{legacy::TransparentAddress, transaction::components::OutPoint},
|
||||
};
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ pub enum WalletMigrationError {
|
|||
|
||||
/// Reverting the specified migration is not supported.
|
||||
CannotRevert(Uuid),
|
||||
|
||||
/// Some other unexpected violation of database business rules occurred
|
||||
Other(SqliteClientError),
|
||||
}
|
||||
|
||||
impl From<rusqlite::Error> for WalletMigrationError {
|
||||
|
@ -79,6 +82,21 @@ impl From<AddressGenerationError> for WalletMigrationError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<SqliteClientError> for WalletMigrationError {
|
||||
fn from(value: SqliteClientError) -> Self {
|
||||
match value {
|
||||
SqliteClientError::CorruptedData(err) => WalletMigrationError::CorruptedData(err),
|
||||
SqliteClientError::DbError(err) => WalletMigrationError::DbError(err),
|
||||
SqliteClientError::CommitmentTree(err) => WalletMigrationError::CommitmentTree(err),
|
||||
SqliteClientError::BalanceError(err) => WalletMigrationError::BalanceError(err),
|
||||
SqliteClientError::AddressGeneration(err) => {
|
||||
WalletMigrationError::AddressGeneration(err)
|
||||
}
|
||||
other => WalletMigrationError::Other(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for WalletMigrationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self {
|
||||
|
@ -106,6 +124,13 @@ impl fmt::Display for WalletMigrationError {
|
|||
WalletMigrationError::CannotRevert(uuid) => {
|
||||
write!(f, "Reverting migration {} is not supported", uuid)
|
||||
}
|
||||
WalletMigrationError::Other(err) => {
|
||||
write!(
|
||||
f,
|
||||
"Unexpected violation of database business rules: {}",
|
||||
err
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +142,7 @@ impl std::error::Error for WalletMigrationError {
|
|||
WalletMigrationError::BalanceError(e) => Some(e),
|
||||
WalletMigrationError::CommitmentTree(e) => Some(e),
|
||||
WalletMigrationError::AddressGeneration(e) => Some(e),
|
||||
WalletMigrationError::Other(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,9 @@ pub(super) fn all_migrations<P: consensus::Parameters + 'static>(
|
|||
params: params.clone(),
|
||||
}),
|
||||
Box::new(spend_key_available::Migration),
|
||||
Box::new(tx_retrieval_queue::Migration),
|
||||
Box::new(tx_retrieval_queue::Migration {
|
||||
params: params.clone(),
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -4,17 +4,21 @@ use rusqlite::{named_params, Transaction};
|
|||
use schemer_rusqlite::RusqliteMigration;
|
||||
use std::collections::HashSet;
|
||||
use uuid::Uuid;
|
||||
use zcash_client_backend::data_api::DecryptedTransaction;
|
||||
use zcash_primitives::transaction::builder::DEFAULT_TX_EXPIRY_DELTA;
|
||||
use zcash_protocol::consensus::{self, BlockHeight, BranchId};
|
||||
|
||||
use crate::wallet::init::WalletMigrationError;
|
||||
use crate::wallet::{self, init::WalletMigrationError};
|
||||
|
||||
use super::utxos_to_txos;
|
||||
|
||||
pub(super) const MIGRATION_ID: Uuid = Uuid::from_u128(0xfec02b61_3988_4b4f_9699_98977fac9e7f);
|
||||
|
||||
pub(crate) struct Migration;
|
||||
pub(super) struct Migration<P> {
|
||||
pub(super) params: P,
|
||||
}
|
||||
|
||||
impl schemer::Migration for Migration {
|
||||
impl<P> schemer::Migration for Migration<P> {
|
||||
fn id(&self) -> Uuid {
|
||||
MIGRATION_ID
|
||||
}
|
||||
|
@ -28,7 +32,7 @@ impl schemer::Migration for Migration {
|
|||
}
|
||||
}
|
||||
|
||||
impl RusqliteMigration for Migration {
|
||||
impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||
type Error = WalletMigrationError;
|
||||
|
||||
fn up(&self, transaction: &Transaction) -> Result<(), WalletMigrationError> {
|
||||
|
@ -75,6 +79,43 @@ impl RusqliteMigration for Migration {
|
|||
named_params![":default_expiry_delta": DEFAULT_TX_EXPIRY_DELTA],
|
||||
)?;
|
||||
|
||||
// Call `decrypt_and_store_transaction` for each transaction known to the wallet to
|
||||
// populate the enhancement queues with any transparent history information that we don't
|
||||
// already have.
|
||||
let mut stmt_transactions =
|
||||
transaction.prepare("SELECT raw, mined_height FROM transactions")?;
|
||||
let mut rows = stmt_transactions.query([])?;
|
||||
while let Some(row) = rows.next()? {
|
||||
let tx_data = row.get::<_, Option<Vec<u8>>>(0)?;
|
||||
let mined_height = row.get::<_, Option<u32>>(1)?.map(BlockHeight::from);
|
||||
|
||||
if let Some(tx_data) = tx_data {
|
||||
let tx = zcash_primitives::transaction::Transaction::read(
|
||||
&tx_data[..],
|
||||
// We assume unmined transactions are created with the current consensus branch ID.
|
||||
mined_height
|
||||
.map_or(BranchId::Sapling, |h| BranchId::for_height(&self.params, h)),
|
||||
)
|
||||
.map_err(|_| {
|
||||
WalletMigrationError::CorruptedData(
|
||||
"Could not read serialized transaction data.".to_owned(),
|
||||
)
|
||||
})?;
|
||||
|
||||
wallet::store_decrypted_tx(
|
||||
transaction,
|
||||
&self.params,
|
||||
DecryptedTransaction::new(
|
||||
mined_height,
|
||||
&tx,
|
||||
vec![],
|
||||
#[cfg(feature = "orchard")]
|
||||
vec![],
|
||||
),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue