Skip to content

Conversation

@iamrecursion
Copy link
Collaborator

This mechanism is intended to be used for the forest implementation with pluggable storage backends. This forest will eventually replace the existing in-memory forest implementation, but for now is being developed in a separate portion of the tree to avoid breakage. We are aiming to merge portions of it incrementally to avoid mammoth PRs and increase visibility, and this mechanism being relatively self-contained makes it a good candidate for this.

This history mechanism is based on the following simplifying assumptions:

  • A forest is generally used to store multiple independent trees and versions of each tree, but does not need to share between those independent trees.
  • Historical versions are not important to persist, and can hence be handled entirely in memory.

The commit contains the basic functionality of this history storage and overlay mechanism, and tests that it functions correctly. It is almost entirely internal code, with little change to the public interface, and as a result temporarily uses #[allow(dead_code)] to keep the build warnings clean. These will be removed in future commits.

The interface for the History in this commit is a best effort at the design, and will likely need to undergo some minor changes to support concurrency as the shape of said concurrency in the forest itself is established.

This is the first bit of work toward #670. I would argue that this does not require a changelog entry as it is not user-facing.

Checklist before requesting a review

  • Repo forked and branch created from next according to naming convention.
  • Commit messages and codestyle follow conventions.
  • Relevant issues are linked in the PR description.
  • Tests added for new functionality.
  • Documentation/comments updated according to changes.

@iamrecursion iamrecursion marked this pull request as draft December 1, 2025 10:29
@iamrecursion iamrecursion force-pushed the forest-history-overlays branch from ba26460 to 4a48680 Compare December 1, 2025 10:31
@iamrecursion iamrecursion marked this pull request as ready for review December 1, 2025 10:34
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Thank you! Not a full review, but I left some comments inline.

Overall, the structure looks good - but we may want to introduce the notion of a version where each historical delta is associated with a numerical version. This should simplify code a bit and would also align better with the use case we have in miden-node.

Also, it would be great if we could use History for AccountTreeWithHistory. This way, we'd reduce the amount of code duplication. I think the interfaces are pretty close, but we should try to make sure that they are indeed aligned.

Comment on lines 147 to 152
pub fn add_version(
&mut self,
root: Word,
nodes: NodeChanges,
leaves: LeafChanges,
) -> Option<Delta> {
Copy link
Contributor

Choose a reason for hiding this comment

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

A couple of potential changes to this API:

  • We could take a MutationSet instead of root, nodes, and leaves as for our specific use case, updates will be generated via mutation sets.
  • I would also pass in a version so that we could associate a given mutation set with a version. This should make pruning of history a bit easier in the future.

Combining the above, I think the signature could look something like this:

pub fn add_version(
    &mut self,
    version: u32,
    updates: MutationSet<SMT_DEPTH, Word, Word>,
) -> Option<Delta> {
    ...
}

@iamrecursion iamrecursion force-pushed the forest-history-overlays branch 2 times, most recently from aaba70f to 0df5dc9 Compare December 3, 2025 15:44
@iamrecursion
Copy link
Collaborator Author

iamrecursion commented Dec 3, 2025

Okay, I have pushed a new commit that addresses all of the feedback except the one comment that I have left unresolved. What follows is a summary of this discussion on Slack.

It seems to me—and I may well be missing something—that we cannot construct the reverse delta information passed to add_version with the forward delta information in MutationSet. That type does not contain the previous value for any of the changes, which in the case of overwrites (of both nodes and leaves) makes it insufficient as a source to construct the reverse delta information.

Note that the History is a container purely for the overlays, and does not have any notion of the tree that it is overlaying.

If we want to make use of MutationSet there are three options in my mind:

  1. Add the previous values to MutationSet at a memory cost, but this has good safety as the MutationSet is only constructed in one place and could store the prior values in the same traversal.
  2. Require taking the MutationSet and an impl SparseMerkleTree. This is footgunny as you have to check at runtime whether the tree and the set actually correspond. I also have concerns whether implementing SparseMerkleTree on the individual trees in the forest's Storage will be able to be done performantly.
  3. Require taking the MutationSet and some auxiliary data that boils down to the reversals only where necessary, but this is very similar to the existing API.

If all you meant was to provide a MutationSet API for the forest itself, this is a separate concern than the API to history, and is definitely planned. The history—and hence calls to things like add_version—are intended to be internal to the tree or forest employing the type, and not client-facing of the tree or forest.

@bobbinth
Copy link
Contributor

bobbinth commented Dec 3, 2025

It seems to me—and I may well be missing something—that we cannot construct the reverse delta information passed to add_version with the forward delta information in MutationSet. That type does not contain the previous value for any of the changes, which in the case of overwrites (of both nodes and leaves) makes it insufficient as a source to construct the reverse delta information.

On Smt and LargeSmt we have methods for this - specifically, apply_mutations_with_reversion(). This method applies the mutations to the underlying tree and returns a mutation set that can be reversed the applies mutations. Whatever data structure we end up using to manage the latest versions of the trees would need to provide similar functionality. Or do you think that could be a problem?

@iamrecursion
Copy link
Collaborator Author

iamrecursion commented Dec 4, 2025

Not at all. The tree or forest—in other words the user-facing construct—will be able to perform this. I just don't think it's something that should live in the history manager itself.

Do you still want the API to talk in terms of MutationSet and assume it is the 'reversed' set, or can we leave it as is for now and make this a future improvement?

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Than you! Not a full review but I left some comments inline.

@iamrecursion iamrecursion force-pushed the forest-history-overlays branch 2 times, most recently from ca66629 to 00250a3 Compare December 8, 2025 11:42
@iamrecursion iamrecursion requested a review from bobbinth December 8, 2025 17:05
@iamrecursion iamrecursion force-pushed the forest-history-overlays branch from 00250a3 to 20ee012 Compare December 8, 2025 17:11
@iamrecursion iamrecursion requested a review from drahnr December 8, 2025 17:11
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Thank you! I left a few small comments inline.

This mechanism is intended to be used for the forest implementation with
pluggable storage backends. This forest will eventually replace the
existing in-memory forest implementation, but for now is being developed
in a separate portion of the tree to avoid breakage. We are aiming to
merge portions of it incrementally to avoid mammoth PRs and increase
visibility, and this mechanism being relatively self-contained makes it
a good candidate for this.

This history mechanism is based on the following simplifying
assumptions:

- A forest is generally used to store multiple independent trees and
  versions of each tree, but does not need to share between those
  independent trees.
- Historical versions are not important to persist, and can hence be
  handled entirely in memory.

The commit contains the basic functionality of this history storage and
overlay mechanism, and tests that it functions correctly. It is almost
entirely internal code, with little change to the public interface, and
as a result temporarily uses `#[allow(dead_code)]` to keep the build
warnings clean. These will be removed in future commits.

The interface for the `History` in this commit is a best effort at the
design, and will likely need to undergo some minor changes to support
concurrency as the shape of said concurrency in the forest itself is
established.
This commit contains a number of changes to the `History` to address PR
feedback. The major changes are:

- Factoring it out into its own portion of the tree as it is now more
  generally applicable than just the forest.
- Adding support for versions in the history items.
- Simplification to the API to eliminate an unneeded feature and thereby
  increase maintainability.
@iamrecursion iamrecursion force-pushed the forest-history-overlays branch from 7eaa60d to d49799c Compare December 9, 2025 13:54
Copy link
Contributor

@drahnr drahnr left a comment

Choose a reason for hiding this comment

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

Two questions, otherwise LGTM

Thank you!

@iamrecursion iamrecursion force-pushed the forest-history-overlays branch from d49799c to 0939968 Compare December 9, 2025 15:48
@iamrecursion iamrecursion added the no changelog This PR does not require an entry in the `CHANGELOG.md` file label Dec 9, 2025
@iamrecursion iamrecursion merged commit 03e8ee0 into 0xMiden:next Dec 9, 2025
24 of 25 checks passed
@iamrecursion iamrecursion deleted the forest-history-overlays branch December 9, 2025 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no changelog This PR does not require an entry in the `CHANGELOG.md` file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants