Add a check to ensure that blocks passed to `put_blocks` are sequential.

This commit is contained in:
Kris Nuttycombe 2023-07-06 08:18:57 -06:00
parent 1b5a24a655
commit d55fa09464
3 changed files with 10 additions and 0 deletions

View File

@ -494,6 +494,8 @@ pub trait WalletWrite: WalletRead {
/// Updates the state of the wallet database by persisting the provided block information,
/// along with the note commitments that were detected when scanning the block for transactions
/// pertaining to this wallet.
///
/// `blocks` must be sequential, in order of increasing block height
fn put_blocks(
&mut self,
block: Vec<ScannedBlock<sapling::Nullifier>>,

View File

@ -57,6 +57,9 @@ pub enum SqliteClientError {
/// different hash. This indicates that a required rewind was not performed.
BlockConflict(BlockHeight),
/// A range of blocks provided to the database as a unit was non-sequential
NonSequentialBlocks,
/// A requested rewind would violate invariants of the storage layer. The payload returned with
/// this error is (safe rewind height, requested height).
RequestedRewindInvalid(BlockHeight, BlockHeight),
@ -118,6 +121,7 @@ impl fmt::Display for SqliteClientError {
SqliteClientError::Io(e) => write!(f, "{}", e),
SqliteClientError::InvalidMemo(e) => write!(f, "{}", e),
SqliteClientError::BlockConflict(h) => write!(f, "A block hash conflict occurred at height {}; rewind required.", u32::from(*h)),
SqliteClientError::NonSequentialBlocks => write!(f, "`put_blocks` requires that the provided block range be sequential"),
SqliteClientError::DiversifierIndexOutOfRange => write!(f, "The space of available diversifier indices is exhausted"),
SqliteClientError::KeyDerivationError(acct_id) => write!(f, "Key derivation failed for account {:?}", acct_id),
SqliteClientError::AccountIdDiscontinuity => write!(f, "Wallet account identifiers must be sequential."),

View File

@ -412,6 +412,10 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
let mut end_height = None;
for block in blocks.into_iter() {
if end_height.iter().any(|prev| block.height() != *prev + 1) {
return Err(SqliteClientError::NonSequentialBlocks);
}
// Insert the block into the database.
wallet::put_block(
wdb.conn.0,