Rename *rewind* to *truncate* in data_api methods.

This better reflects the semantics of wallet behavior. Also, this
adds a `zcash_client_backend::WalletRead::get_min_unspent_height`
method that replaces the deprecated & removed (and misleadingly
named) `get_rewind_height` method.
This commit is contained in:
Kris Nuttycombe 2023-04-26 16:27:56 -06:00
parent 7405d0cd69
commit ac3439e65e
6 changed files with 42 additions and 22 deletions

View File

@ -9,11 +9,12 @@ and this library adheres to Rust's notion of
### Added ### Added
- `data_api::SentTransactionOutput::from_parts` - `data_api::SentTransactionOutput::from_parts`
- `data_api::SentTransactionOutput::sapling_change_to` - `data_api::SentTransactionOutput::sapling_change_to`
- `data_api::WalletRead::get_min_unspent_height`
### Changed ### Changed
- `decrypt::DecryptedOutput` is now parameterized by a `Note` type parameter, - `decrypt::DecryptedOutput` is now parameterized by a `Note` type parameter,
to allow reuse of the data structure for non-Sapling contexts. to allow reuse of the data structure for non-Sapling contexts.
- `data_api::SentTransactionOutput` must now be constructed using - `data_api::SentTransactionOutput` must now be constructed using
`SentTransactionOutput::from_parts` `SentTransactionOutput::from_parts`
### Renamed ### Renamed
@ -25,6 +26,8 @@ and this library adheres to Rust's notion of
data structure have been made private. data structure have been made private.
- `WalletShieldedOutput` -> `WalletSaplingOutput`. Also, the internals of this - `WalletShieldedOutput` -> `WalletSaplingOutput`. Also, the internals of this
data structure have been made private. data structure have been made private.
- The `data_api::WalletWrite::rewind_to_height` method has been renamed to
`truncate_to_height` to better reflect its semantics.
### Removed ### Removed
- `wallet::WalletTx::num_spends` - `wallet::WalletTx::num_spends`

View File

@ -83,6 +83,9 @@ pub trait WalletRead {
}) })
} }
/// Returns the minimum block height corresponding to an unspent note in the wallet.
fn get_min_unspent_height(&self) -> Result<Option<BlockHeight>, Self::Error>;
/// Returns the block hash for the block at the given height, if the /// Returns the block hash for the block at the given height, if the
/// associated block data is available. Returns `Ok(None)` if the hash /// associated block data is available. Returns `Ok(None)` if the hash
/// is not found in the database. /// is not found in the database.
@ -361,7 +364,7 @@ pub trait WalletWrite: WalletRead {
/// persistent wallet store. /// persistent wallet store.
fn store_sent_tx(&mut self, sent_tx: &SentTransaction) -> Result<Self::TxRef, Self::Error>; fn store_sent_tx(&mut self, sent_tx: &SentTransaction) -> Result<Self::TxRef, Self::Error>;
/// Rewinds the wallet database to the specified height. /// Truncates the wallet database to the specified height.
/// ///
/// This method assumes that the state of the underlying data store is /// This method assumes that the state of the underlying data store is
/// consistent up to a particular block height. Since it is possible that /// consistent up to a particular block height. Since it is possible that
@ -373,8 +376,8 @@ pub trait WalletWrite: WalletRead {
/// most recent block and all other operations will treat this block /// most recent block and all other operations will treat this block
/// as the chain tip for balance determination purposes. /// as the chain tip for balance determination purposes.
/// ///
/// There may be restrictions on how far it is possible to rewind. /// There may be restrictions on heights to which it is possible to truncate.
fn rewind_to_height(&mut self, block_height: BlockHeight) -> Result<(), Self::Error>; fn truncate_to_height(&mut self, block_height: BlockHeight) -> Result<(), Self::Error>;
/// Adds a transparent UTXO received by the wallet to the data store. /// Adds a transparent UTXO received by the wallet to the data store.
fn put_received_transparent_utxo( fn put_received_transparent_utxo(
@ -423,6 +426,10 @@ pub mod testing {
Ok(None) Ok(None)
} }
fn get_min_unspent_height(&self) -> Result<Option<BlockHeight>, Self::Error> {
Ok(None)
}
fn get_block_hash( fn get_block_hash(
&self, &self,
_block_height: BlockHeight, _block_height: BlockHeight,
@ -588,7 +595,7 @@ pub mod testing {
Ok(TxId::from_bytes([0u8; 32])) Ok(TxId::from_bytes([0u8; 32]))
} }
fn rewind_to_height(&mut self, _block_height: BlockHeight) -> Result<(), Self::Error> { fn truncate_to_height(&mut self, _block_height: BlockHeight) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }

View File

@ -55,7 +55,7 @@
//! let rewind_height = e.at_height() - 10; //! let rewind_height = e.at_height() - 10;
//! //!
//! // b) Rewind scanned block information. //! // b) Rewind scanned block information.
//! db_data.rewind_to_height(rewind_height); //! db_data.truncate_to_height(rewind_height);
//! //!
//! // c) Delete cached blocks from rewind_height onwards. //! // c) Delete cached blocks from rewind_height onwards.
//! // //! //

View File

@ -141,7 +141,7 @@ pub(crate) fn blockmetadb_insert(
} }
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub(crate) fn blockmetadb_rewind_to_height( pub(crate) fn blockmetadb_truncate_to_height(
conn: &Connection, conn: &Connection,
block_height: BlockHeight, block_height: BlockHeight,
) -> Result<(), rusqlite::Error> { ) -> Result<(), rusqlite::Error> {
@ -284,7 +284,7 @@ mod tests {
self, fake_compact_block, fake_compact_block_spending, init_test_accounts_table, self, fake_compact_block, fake_compact_block_spending, init_test_accounts_table,
insert_into_cache, sapling_activation_height, AddressType, insert_into_cache, sapling_activation_height, AddressType,
}, },
wallet::{get_balance, init::init_wallet_db, rewind_to_height}, wallet::{get_balance, init::init_wallet_db, truncate_to_height},
AccountId, BlockDb, WalletDb, AccountId, BlockDb, WalletDb,
}; };
@ -479,7 +479,7 @@ mod tests {
} }
#[test] #[test]
fn data_db_rewinding() { fn data_db_truncation() {
let cache_file = NamedTempFile::new().unwrap(); let cache_file = NamedTempFile::new().unwrap();
let db_cache = BlockDb::for_path(cache_file.path()).unwrap(); let db_cache = BlockDb::for_path(cache_file.path()).unwrap();
init_cache_database(&db_cache).unwrap(); init_cache_database(&db_cache).unwrap();
@ -529,7 +529,7 @@ mod tests {
); );
// "Rewind" to height of last scanned block // "Rewind" to height of last scanned block
rewind_to_height(&db_data, sapling_activation_height() + 1).unwrap(); truncate_to_height(&db_data, sapling_activation_height() + 1).unwrap();
// Account balance should be unaltered // Account balance should be unaltered
assert_eq!( assert_eq!(
@ -538,7 +538,7 @@ mod tests {
); );
// Rewind so that one block is dropped // Rewind so that one block is dropped
rewind_to_height(&db_data, sapling_activation_height()).unwrap(); truncate_to_height(&db_data, sapling_activation_height()).unwrap();
// Account balance should only contain the first received note // Account balance should only contain the first received note
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value); assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);

View File

@ -139,6 +139,10 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
wallet::block_height_extrema(self).map_err(SqliteClientError::from) wallet::block_height_extrema(self).map_err(SqliteClientError::from)
} }
fn get_min_unspent_height(&self) -> Result<Option<BlockHeight>, Self::Error> {
wallet::get_min_unspent_height(self).map_err(SqliteClientError::from)
}
fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> { fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> {
wallet::get_block_hash(self, block_height).map_err(SqliteClientError::from) wallet::get_block_hash(self, block_height).map_err(SqliteClientError::from)
} }
@ -294,6 +298,10 @@ impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
self.wallet_db.block_height_extrema() self.wallet_db.block_height_extrema()
} }
fn get_min_unspent_height(&self) -> Result<Option<BlockHeight>, Self::Error> {
self.wallet_db.get_min_unspent_height()
}
fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> { fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> {
self.wallet_db.get_block_hash(block_height) self.wallet_db.get_block_hash(block_height)
} }
@ -675,8 +683,8 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> {
}) })
} }
fn rewind_to_height(&mut self, block_height: BlockHeight) -> Result<(), Self::Error> { fn truncate_to_height(&mut self, block_height: BlockHeight) -> Result<(), Self::Error> {
wallet::rewind_to_height(self.wallet_db, block_height) wallet::truncate_to_height(self.wallet_db, block_height)
} }
fn put_received_transparent_utxo( fn put_received_transparent_utxo(
@ -875,8 +883,8 @@ impl FsBlockDb {
/// If the requested height is greater than or equal to the height /// If the requested height is greater than or equal to the height
/// of the last scanned block, or if the DB is empty, this function /// of the last scanned block, or if the DB is empty, this function
/// does nothing. /// does nothing.
pub fn rewind_to_height(&self, block_height: BlockHeight) -> Result<(), FsBlockDbError> { pub fn truncate_to_height(&self, block_height: BlockHeight) -> Result<(), FsBlockDbError> {
Ok(chain::blockmetadb_rewind_to_height( Ok(chain::blockmetadb_truncate_to_height(
&self.conn, &self.conn,
block_height, block_height,
)?) )?)
@ -1363,7 +1371,9 @@ mod tests {
assert_eq!(db_meta.find_block(BlockHeight::from_u32(3)).unwrap(), None); assert_eq!(db_meta.find_block(BlockHeight::from_u32(3)).unwrap(), None);
// Rewinding to height 1 should cause the metadata for height 2 to be deleted. // Rewinding to height 1 should cause the metadata for height 2 to be deleted.
db_meta.rewind_to_height(BlockHeight::from_u32(1)).unwrap(); db_meta
.truncate_to_height(BlockHeight::from_u32(1))
.unwrap();
assert_eq!( assert_eq!(
db_meta.get_max_cached_height().unwrap(), db_meta.get_max_cached_height().unwrap(),
Some(BlockHeight::from_u32(1)), Some(BlockHeight::from_u32(1)),

View File

@ -583,9 +583,9 @@ pub(crate) fn get_block_hash<P>(
.optional() .optional()
} }
/// Gets the height to which the database must be rewound if any rewind greater than the pruning /// Gets the height to which the database must be truncated if any truncation that would remove a
/// height is attempted. /// number of blocks greater than the pruning height is attempted.
pub(crate) fn get_rewind_height<P>( pub(crate) fn get_min_unspent_height<P>(
wdb: &WalletDb<P>, wdb: &WalletDb<P>,
) -> Result<Option<BlockHeight>, SqliteClientError> { ) -> Result<Option<BlockHeight>, SqliteClientError> {
wdb.conn wdb.conn
@ -603,13 +603,13 @@ pub(crate) fn get_rewind_height<P>(
.map_err(SqliteClientError::from) .map_err(SqliteClientError::from)
} }
/// Rewinds the database to the given height. /// Truncates the database to the given height.
/// ///
/// If the requested height is greater than or equal to the height of the last scanned /// If the requested height is greater than or equal to the height of the last scanned
/// block, this function does nothing. /// block, this function does nothing.
/// ///
/// This should only be executed inside a transactional context. /// This should only be executed inside a transactional context.
pub(crate) fn rewind_to_height<P: consensus::Parameters>( pub(crate) fn truncate_to_height<P: consensus::Parameters>(
wdb: &WalletDb<P>, wdb: &WalletDb<P>,
block_height: BlockHeight, block_height: BlockHeight,
) -> Result<(), SqliteClientError> { ) -> Result<(), SqliteClientError> {
@ -628,7 +628,7 @@ pub(crate) fn rewind_to_height<P: consensus::Parameters>(
})?; })?;
if block_height < last_scanned_height - PRUNING_HEIGHT { if block_height < last_scanned_height - PRUNING_HEIGHT {
if let Some(h) = get_rewind_height(wdb)? { if let Some(h) = get_min_unspent_height(wdb)? {
if block_height > h { if block_height > h {
return Err(SqliteClientError::RequestedRewindInvalid(h, block_height)); return Err(SqliteClientError::RequestedRewindInvalid(h, block_height));
} }