Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shardtree: Add the ability to avoid pruning specific checkpoints. #95

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

nuttycom
Copy link
Contributor

No description provided.

@nuttycom nuttycom force-pushed the explicit_checkpoint_retention branch from f4d43b5 to 34b1a5f Compare January 19, 2024 19:29
Copy link
Contributor

@str4d str4d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 34b1a5f.

Comment on lines 117 to 118
/// Adds the provided checkpoint to the set of checkpoints to be retained
/// across pruning operations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API needs a bit more documentation, because it is unclear whether or not this data being stored in ShardTree means it needs to be serialized. In particular, we should document that this API needs to be called after constructing ShardTree but before calling any methods that take &mut self (or whatever other criterion gates potential pruning). An example would be ideal:

Suggested change
/// Adds the provided checkpoint to the set of checkpoints to be retained
/// across pruning operations.
/// Adds the provided checkpoint to the set of checkpoints to be retained
/// across pruning operations.
///
/// TODO: A bit more documentation.
///
/// # Examples
///
/// ```
/// use incrementalmerkletree::Retention;
/// use shardtree::ShardTree;
///
/// # fn load_shardtree_from_disk() -> ShardTree<SomeShardStore> {
/// # todo!("Kris returns something useful for testing here.")
/// # }
/// # fn checkpoints_to_retain() -> Vec<SomeCheckpointId> {
/// # vec![] // TODO: Return something useful for testing here.
/// # }
/// # fn get_next_leaf() -> SomeLeafType {
/// # todo!("Kris returns something useful for testing here.")
/// # }
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut tree = load_shardtree_from_disk();
///
/// // The required checkpoints are stored separately from the tree.
/// for checkpoint_id in checkpoints_to_retain() {
/// tree.ensure_retained(checkpoint_id);
/// }
///
/// // Now perform operations that might prune the tree.
/// tree.append(get_next_leaf(), Retention::Ephemeral)?;
/// # Ok(())
/// # }
/// ```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I guess maybe I should actually add this to the ShardStore interface, so that it's up to the implementer of that to decide whether or not the explicitly retained items are represented in the serialization. In the zcash_client_sqlite database, they'll actually be serialized; the retained checkpoint identifier will always be the block height prior to the earliest unscanned FoundNote or ChainTip range, and each time we go to perform a put_blocks operation, we'll check whether the operation has increased that height.

It gets a little complicated, because Historic and OpenAdjacent scanning can find notes at lower heights than the current "high water mark" - in the event that that happens, the value of those notes can't be added to the available balance until their entire subtrees are scanned. This leads to an uncomfortable situation where you might be able to increase the available balance if you were to choose a lower checkpoint height, for example if you have a small spendable note at the chain tip, but then discover a large spendable note at a lower height.

shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
shardtree/src/lib.rs Outdated Show resolved Hide resolved
assert_matches!(
tree.witness_at_checkpoint_id(Position::from(4), &12),
Ok(w) if w == e_witness_12
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test case where we request to retain a checkpoint that is within the range of checkpoints that would already be retained. This is to exercise the self.max_checkpoints + self.to_retain.len() behaviour I questioned above; we should have a case that checks whichever behaviour we go with.

@nuttycom nuttycom force-pushed the explicit_checkpoint_retention branch from 2f17533 to 5042984 Compare January 22, 2024 21:07
@nuttycom nuttycom requested a review from str4d January 23, 2024 19:22
@@ -66,8 +66,8 @@ mod legacy;
pub struct ShardTree<S: ShardStore, const DEPTH: u8, const SHARD_HEIGHT: u8> {
/// The vector of tree shards.
store: S,
/// The maximum number of checkpoints to retain before pruning.
max_checkpoints: usize,
/// The minumum number of checkpoints to retain when pruning.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The minumum number of checkpoints to retain when pruning.
/// The minimum number of checkpoints to retain when pruning.

@@ -79,10 +79,10 @@ impl<
> ShardTree<S, DEPTH, SHARD_HEIGHT>
{
/// Creates a new empty tree.
pub fn new(store: S, max_checkpoints: usize) -> Self {
pub fn new(store: S, min_checkpoints_to_retain: usize) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems quite a significant semantic change for something that retains the same type signature. Is it the case that previous callers will be correct for the new semantics? In any case please document the parameter.

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK with comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants