Skip to content

Conversation

@felipet
Copy link
Collaborator

@felipet felipet commented Nov 10, 2025

This PR includes the changes required to make the entire library's modules async ready, i.e. all the modules shall implement the traits Send & Sync.

All the stores that made use of an external lib were already async ready, but SQLite, whose library doesn't fully support async code (it's Send but not Sync). I'd suggest leaving the store for SQLite outside the scope of this feature, or change the used library to another that wraps SQLite to be Send & Sync (the best choice is SQLx.

Thus, the main change introduced in this PR affects the struct MemoryStore and the struct MerkleProof.

Overview of the changes

The structs: MemoryStore and MerkleProof have been wrapped using a common design pattern in Rust. The former struct definitions were renamed to MemoryStoreInner and MerkleProofInner, and 2 new structs have been defined with the base names MemoryStore and MerkleProof that include an only field: an instance of the inner counterpart. This way, it is quite simple to ensure thread safety, as the entire inner struct is locked by a single lock.

Multiple reads are allowed, and only one writer at a time. The choice to wrap the entire struct with a single lock is motivated by the fact that write methods modify most of the internal fields at the same time. So rather than wrap every field with its own lock, I chose wrapping the entire struct. This should lead to a safer operation, as the risk of deadlocks gets reduced.

A new error type was included to signal a lock poisoning.

Benchmarking

The changes haven't affected the overall performance of the library:

Results before the changes:

### `add_leaves` throughput

| Depth | Hash | Store | Throughput (Kelem/s) |
|---|---|---|---|
| 32 | keccak256 | rocksdb | 14.801 |
| 32 | keccak256 | sqlite | 18.026 |
| 32 | keccak256 | sled | 38.815 |
| 32 | keccak256 | memory | 78.693 |

### `proof` time

| Depth | Hash | Store | Time |
|---|---|---|---|
| 32 | keccak256 | memory | 710.860 ns |
| 32 | keccak256 | sled | 10.478 µs |
| 32 | keccak256 | sqlite | 20.286 µs |
| 32 | keccak256 | rocksdb | 47.383 µs |

Results after the change:

### `add_leaves` throughput

| Depth | Hash | Store | Throughput (Kelem/s) |
|---|---|---|---|
| 32 | keccak256 | rocksdb | 15.518 |
| 32 | keccak256 | sqlite | 17.696 |
| 32 | keccak256 | sled | 37.574 |
| 32 | keccak256 | memory | 77.473 |

### `proof` time

| Depth | Hash | Store | Time |
|---|---|---|---|
| 32 | keccak256 | memory | 749.490 ns |
| 32 | keccak256 | sled | 10.855 µs |
| 32 | keccak256 | sqlite | 20.701 µs |
| 32 | keccak256 | rocksdb | 34.575 µs |

The addition of leaves for the memory store has slightly lowered its performance, as expected.

@felipet
Copy link
Collaborator Author

felipet commented Nov 10, 2025

@alrevuelta let me know if you're happy with leaving outside the async support for the SQLite store.

@felipet felipet requested a review from alrevuelta November 10, 2025 14:42
@felipet felipet self-assigned this Nov 10, 2025
@felipet felipet added the enhancement New feature or request label Nov 10, 2025
@codecov
Copy link

codecov bot commented Nov 10, 2025

Codecov Report

❌ Patch coverage is 67.69231% with 21 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/tree.rs 66.07% 19 Missing ⚠️
src/stores/memory_store.rs 77.77% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants