zcash_client_sqlite: Avoid attempting to re-create already-pruned checkpoints.

This commit is contained in:
Kris Nuttycombe 2024-03-22 19:41:52 -06:00
parent 5d3ddabe24
commit 635057d86f
1 changed files with 52 additions and 23 deletions

View File

@ -612,7 +612,7 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
Ok(()) Ok(())
} }
#[tracing::instrument(skip_all, fields(height = blocks.first().map(|b| u32::from(b.height()))))] #[tracing::instrument(skip_all, fields(height = blocks.first().map(|b| u32::from(b.height())), count = blocks.len()))]
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
fn put_blocks( fn put_blocks(
&mut self, &mut self,
@ -881,16 +881,17 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
} }
#[cfg(feature = "orchard")] #[cfg(feature = "orchard")]
let missing_sapling_checkpoints = ensure_checkpoints( let (missing_sapling_checkpoints, missing_orchard_checkpoints) = (
orchard_checkpoint_positions.keys(), ensure_checkpoints(
&sapling_checkpoint_positions, orchard_checkpoint_positions.keys(),
from_state.final_sapling_tree(), &sapling_checkpoint_positions,
); from_state.final_sapling_tree(),
#[cfg(feature = "orchard")] ),
let missing_orchard_checkpoints = ensure_checkpoints( ensure_checkpoints(
sapling_checkpoint_positions.keys(), sapling_checkpoint_positions.keys(),
&orchard_checkpoint_positions, &orchard_checkpoint_positions,
from_state.final_orchard_tree(), from_state.final_orchard_tree(),
),
); );
// Update the Sapling note commitment tree with all newly read note commitments // Update the Sapling note commitment tree with all newly read note commitments
@ -909,13 +910,27 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
sapling_tree.insert_tree(tree, checkpoints)?; sapling_tree.insert_tree(tree, checkpoints)?;
} }
// Ensure we have a Sapling checkpoint for each checkpointed Orchard block height // Ensure we have a Sapling checkpoint for each checkpointed Orchard block height.
// We skip all checkpoints below the minimum retained checkpoint in the
// Sapling tree, because branches below this height may be pruned.
#[cfg(feature = "orchard")] #[cfg(feature = "orchard")]
for (height, checkpoint) in &missing_sapling_checkpoints { {
sapling_tree let min_checkpoint_height = sapling_tree
.store_mut() .store()
.add_checkpoint(*height, checkpoint.clone()) .min_checkpoint_id()
.map_err(ShardTreeError::Storage)?; .map_err(ShardTreeError::Storage)?
.expect(
"At least one checkpoint was inserted (by insert_frontier)",
);
for (height, checkpoint) in &missing_sapling_checkpoints {
if *height > min_checkpoint_height {
sapling_tree
.store_mut()
.add_checkpoint(*height, checkpoint.clone())
.map_err(ShardTreeError::Storage)?;
}
}
} }
Ok(()) Ok(())
@ -939,13 +954,27 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
orchard_tree.insert_tree(tree, checkpoints)?; orchard_tree.insert_tree(tree, checkpoints)?;
} }
for (height, checkpoint) in &missing_orchard_checkpoints { // Ensure we have an Orchard checkpoint for each checkpointed Sapling block height.
orchard_tree // We skip all checkpoints below the minimum retained checkpoint in the
.store_mut() // Orchard tree, because branches below this height may be pruned.
.add_checkpoint(*height, checkpoint.clone()) {
.map_err(ShardTreeError::Storage)?; let min_checkpoint_height = orchard_tree
} .store()
.min_checkpoint_id()
.map_err(ShardTreeError::Storage)?
.expect(
"At least one checkpoint was inserted (by insert_frontier)",
);
for (height, checkpoint) in &missing_orchard_checkpoints {
if *height > min_checkpoint_height {
orchard_tree
.store_mut()
.add_checkpoint(*height, checkpoint.clone())
.map_err(ShardTreeError::Storage)?;
}
}
}
Ok(()) Ok(())
})?; })?;
} }