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) = (
ensure_checkpoints(
orchard_checkpoint_positions.keys(), orchard_checkpoint_positions.keys(),
&sapling_checkpoint_positions, &sapling_checkpoint_positions,
from_state.final_sapling_tree(), from_state.final_sapling_tree(),
); ),
#[cfg(feature = "orchard")] ensure_checkpoints(
let missing_orchard_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,14 +910,28 @@ 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")]
{
let min_checkpoint_height = sapling_tree
.store()
.min_checkpoint_id()
.map_err(ShardTreeError::Storage)?
.expect(
"At least one checkpoint was inserted (by insert_frontier)",
);
for (height, checkpoint) in &missing_sapling_checkpoints { for (height, checkpoint) in &missing_sapling_checkpoints {
if *height > min_checkpoint_height {
sapling_tree sapling_tree
.store_mut() .store_mut()
.add_checkpoint(*height, checkpoint.clone()) .add_checkpoint(*height, checkpoint.clone())
.map_err(ShardTreeError::Storage)?; .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)?;
} }
// Ensure we have an Orchard checkpoint for each checkpointed Sapling block height.
// We skip all checkpoints below the minimum retained checkpoint in the
// Orchard tree, because branches below this height may be pruned.
{
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 { for (height, checkpoint) in &missing_orchard_checkpoints {
if *height > min_checkpoint_height {
orchard_tree orchard_tree
.store_mut() .store_mut()
.add_checkpoint(*height, checkpoint.clone()) .add_checkpoint(*height, checkpoint.clone())
.map_err(ShardTreeError::Storage)?; .map_err(ShardTreeError::Storage)?;
} }
}
}
Ok(()) Ok(())
})?; })?;
} }