Add a check to ensure that blocks passed to `put_blocks` are sequential.
This commit is contained in:
parent
1b5a24a655
commit
d55fa09464
|
@ -494,6 +494,8 @@ pub trait WalletWrite: WalletRead {
|
||||||
/// Updates the state of the wallet database by persisting the provided block information,
|
/// 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
|
/// along with the note commitments that were detected when scanning the block for transactions
|
||||||
/// pertaining to this wallet.
|
/// pertaining to this wallet.
|
||||||
|
///
|
||||||
|
/// `blocks` must be sequential, in order of increasing block height
|
||||||
fn put_blocks(
|
fn put_blocks(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: Vec<ScannedBlock<sapling::Nullifier>>,
|
block: Vec<ScannedBlock<sapling::Nullifier>>,
|
||||||
|
|
|
@ -57,6 +57,9 @@ pub enum SqliteClientError {
|
||||||
/// different hash. This indicates that a required rewind was not performed.
|
/// different hash. This indicates that a required rewind was not performed.
|
||||||
BlockConflict(BlockHeight),
|
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
|
/// A requested rewind would violate invariants of the storage layer. The payload returned with
|
||||||
/// this error is (safe rewind height, requested height).
|
/// this error is (safe rewind height, requested height).
|
||||||
RequestedRewindInvalid(BlockHeight, BlockHeight),
|
RequestedRewindInvalid(BlockHeight, BlockHeight),
|
||||||
|
@ -118,6 +121,7 @@ impl fmt::Display for SqliteClientError {
|
||||||
SqliteClientError::Io(e) => write!(f, "{}", e),
|
SqliteClientError::Io(e) => write!(f, "{}", e),
|
||||||
SqliteClientError::InvalidMemo(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::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::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::KeyDerivationError(acct_id) => write!(f, "Key derivation failed for account {:?}", acct_id),
|
||||||
SqliteClientError::AccountIdDiscontinuity => write!(f, "Wallet account identifiers must be sequential."),
|
SqliteClientError::AccountIdDiscontinuity => write!(f, "Wallet account identifiers must be sequential."),
|
||||||
|
|
|
@ -412,6 +412,10 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
|
||||||
let mut end_height = None;
|
let mut end_height = None;
|
||||||
|
|
||||||
for block in blocks.into_iter() {
|
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.
|
// Insert the block into the database.
|
||||||
wallet::put_block(
|
wallet::put_block(
|
||||||
wdb.conn.0,
|
wdb.conn.0,
|
||||||
|
|
Loading…
Reference in New Issue