Skip to content

Conversation

@RodrigoVillar
Copy link
Contributor

@RodrigoVillar RodrigoVillar commented Oct 29, 2025

This PR adds FjallStore, an implementation of RootStore that allows for persistent storage of revisions (in contrast to MockStore, which keeps everything in-memory). The main changes of this PR are as follows:

  • Adds FjallStore implementation
  • Extends the DbConfig to take in a path to where FjallStore will be stored
  • Extends the FFI database config to enable archival support
  • Adds FjallStore tests in both Rust and Golang

@RodrigoVillar RodrigoVillar self-assigned this Oct 29, 2025
@RodrigoVillar RodrigoVillar added the DO NOT MERGE This PR is not meant to be merged in its current state label Oct 29, 2025
@RodrigoVillar RodrigoVillar removed the DO NOT MERGE This PR is not meant to be merged in its current state label Nov 3, 2025
@RodrigoVillar RodrigoVillar added the DO NOT MERGE This PR is not meant to be merged in its current state label Nov 5, 2025
@RodrigoVillar
Copy link
Contributor Author

RodrigoVillar commented Nov 5, 2025

Note to reviewers: I've marked the PR as DO NOT MERGE since I'm working on getting benchmark results for Firewood + FjallStore when compared to LevelDB (and we should only merge once we have benchmark results). However, I figured we can get the code review process going since benchmarking can take place async.

@RodrigoVillar RodrigoVillar marked this pull request as ready for review November 5, 2025 14:47
Copy link
Member

@rkuris rkuris left a comment

Choose a reason for hiding this comment

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

I'm not sure I love changing the reaping logic to fix this issue. The commit should have the ability to reap any revision at any time.

I think there are a few possible approaches here:

1 - Part of reaping is adding it to the RootStore
2 - Every commit adds to RootStore so entries are both in the RootStore and in the revision manager (preferred).

@rkuris
Copy link
Member

rkuris commented Nov 15, 2025

Note to reviewers: I've marked the PR as DO NOT MERGE since I'm working on getting benchmark results for Firewood + FjallStore when compared to LevelDB (and we should only merge once we have benchmark results). However, I figured we can get the code review process going since benchmarking can take place async.

I think we determined that this PR does not affect performance, so I think this is mergeable at this point.

@RodrigoVillar RodrigoVillar removed the DO NOT MERGE This PR is not meant to be merged in its current state label Nov 17, 2025
@RodrigoVillar RodrigoVillar requested a review from rkuris November 17, 2025 21:35
Copy link
Member

@rkuris rkuris left a comment

Choose a reason for hiding this comment

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

I'm not sure I love the separation of concerns here, but I could be convinced it's okay.

Perhaps the Rootstore interface should be that it returns nodestores themselves, and then the RootStore can deal with its own caching (only in the real implementation).

I think that cleans up the manager itself to focus on doing what it's supposed to be doing (tracking nodestores) instead of constructing them.

@RodrigoVillar
Copy link
Contributor Author

@rkuis I'm definitely on-board with having RootStore own constructing and maintaining its own nodestores. With our current code, refactoring would fail due to the following circular dependency:

stateDiagram-v2
    s1: Revision Manager
    s2: RootStore

    s1 --> s2: Wants historical revision X
    s2 --> s1: Wants latest revision
Loading

One way to fix this would be to pass in the latest revision to get():

fn get(
        &self,
        hash: &TrieHash,
        latest_revision: CommittedRevision,
    ) -> Result<Option<LinearAddress>, Box<dyn std::error::Error + Send + Sync>>;

However, passing in the latest revision seems odd (we expect RootStore to handle it's own nodestores). I think the better alternative would be to delegate the historical and by_hash fields of the RevisionManager into their own DS and have that be shared by both the RevisionManager and RootStore:

pub struct InMemoryRevisions {
    historical: VecDeque<CommittedRevision>,
    by_hash: HashMap<TrieHash, CommittedRevision>
}

Refactoring our code to use this DS would lead to the following dependency graph:

stateDiagram-v2
    s1: Revision Manager
    s2: RootStore
    s3: InMemoryRevisions

    s1 --> s3: Maintains latest revisions
    s1 --> s2: Wants historical revision
    s2 --> s3: Wants latest revision
Loading

@rkuris
Copy link
Member

rkuris commented Nov 18, 2025

pub struct InMemoryRevisions {
    historical: VecDeque<CommittedRevision>,
    by_hash: HashMap<TrieHash, CommittedRevision>
}

Let's enter a new issue and do this. We should also have methods on this struct to manage and fetch from the list.

@rkuris rkuris self-requested a review November 18, 2025 17:16
Copy link
Member

@rkuris rkuris left a comment

Choose a reason for hiding this comment

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

Approved on creation of a followup for simplifying management of in memory revisions.

@RodrigoVillar
Copy link
Contributor Author

Created #1470 which will track this.

@RodrigoVillar RodrigoVillar enabled auto-merge (squash) November 18, 2025 17:35
@RodrigoVillar RodrigoVillar merged commit 8b6e408 into main Nov 18, 2025
45 checks passed
@RodrigoVillar RodrigoVillar deleted the rodrigo/add-root-store-alpha branch November 18, 2025 17:43
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.

feat(firewood/ffi): add production RootStore implementation

4 participants