Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3e6f29b
feat(private-document-store): add grovedb-private-document-store crate
QuantumExplorer Aug 3, 2026
26a804b
feat: add PrivateDocumentStore element type, gated to GROVE_V4 (#784)
QuantumExplorer Aug 3, 2026
7df52c3
test: raise PrivateDocumentStore patch coverage above the 90% codecov…
QuantumExplorer Aug 3, 2026
fff8363
fix: address CodeRabbit review on PrivateDocumentStore (PR #787)
QuantumExplorer Aug 3, 2026
b94da45
Merge origin/develop into feat/private-document-store
QuantumExplorer Aug 17, 2026
3f1d03e
fix: address the PrivateDocumentStore review findings (PR #787)
QuantumExplorer Aug 19, 2026
677508a
Merge remote-tracking branch 'origin/develop' into feat/private-docum…
QuantumExplorer Aug 19, 2026
4db7b47
fix: thread the declared chunk power into PrivateDocumentStore estimates
QuantumExplorer Aug 19, 2026
637b3ab
fix: address the second review round on PrivateDocumentStore (PR #787)
QuantumExplorer Aug 19, 2026
a6533cd
fix: bill the uncached MMR root read on the lazy path (PR #787)
QuantumExplorer Aug 19, 2026
1d2304c
fix: address the review-body findings on PrivateDocumentStore (PR #787)
QuantumExplorer Aug 19, 2026
2a90139
fix(costs): correct five hash and seek accounting errors on the store…
QuantumExplorer Aug 19, 2026
f05222d
test(pds): cover the corruption and storage-fault paths
QuantumExplorer Aug 19, 2026
540504b
fix(costs): bill compaction work and MMR merge hashes
QuantumExplorer Aug 19, 2026
b7aa74f
fix(costs): drop the duplicated MMR merge charge, and report bagging
QuantumExplorer Aug 19, 2026
f5fb2a7
feat(version): gate the MMR hash-charge corrections behind V0/V1
QuantumExplorer Aug 19, 2026
0e404d6
fix(costs): gate the CommitmentTree compaction under-charge into V4
QuantumExplorer Aug 19, 2026
6fa3277
fix(bulk-append): drop the dead initializer flagged by -D warnings
QuantumExplorer Aug 19, 2026
2c2e95c
refactor: take grove_version directly instead of paired _with_version…
QuantumExplorer Aug 20, 2026
11768ae
refactor(mmr): take grove_version directly on push, get_root and gen_…
QuantumExplorer Aug 20, 2026
f6e76c9
test(pds): cover the empty-at-creation guard on total_count
QuantumExplorer Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"grovedb-bulk-append-tree",
"grovedb-dense-fixed-sized-merkle-tree",
"grovedb-query",
"grovedb-private-document-store",
]

[workspace.dependencies]
Expand Down
3 changes: 3 additions & 0 deletions grovedb-bulk-append-tree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ storage = [
"grovedb-dense-fixed-sized-merkle-tree/storage",
]
mem_store = ["grovedb-merkle-mountain-range/mem_store"]
# Exposes `test_utils::MemStorageContext` to other crates' test builds so the
# in-memory StorageContext harness lives in exactly one place.
test-utils = ["storage"]

[dependencies]
grovedb-merkle-mountain-range = { version = "5.0.1", path = "../grovedb-merkle-mountain-range", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions grovedb-bulk-append-tree/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ mod error;
pub mod proof;
mod tree;

#[cfg(all(test, feature = "storage"))]
pub(crate) mod test_utils;
#[cfg(all(feature = "storage", any(test, feature = "test-utils")))]
pub mod test_utils;

// Re-export main types
pub use chunk::{deserialize_chunk_blob, serialize_chunk_blob};
Expand Down
46 changes: 42 additions & 4 deletions grovedb-bulk-append-tree/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Test utilities: in-memory StorageContext for BulkAppendTree tests.

use std::{cell::RefCell, collections::HashMap};
use std::{
cell::{Cell, RefCell},
collections::HashMap,
};

use grovedb_costs::{
storage_cost::key_value_cost::KeyValueStorageCost, ChildrenSizesWithIsSumTree, CostContext,
Expand All @@ -13,22 +16,51 @@ use grovedb_storage::{Batch, RawIterator, StorageContext};
/// Immediate reads and writes backed by a `HashMap`. Only `get` and `put`
/// (data storage) have real implementations; all other `StorageContext`
/// methods panic if called.
///
/// `fail_get` / `fail_put` inject storage faults. Tree code is full of arms
/// that can only be reached when the backing store errors mid-operation —
/// exactly the paths that decide whether a fault surfaces or is silently
/// swallowed — and without injection those arms are untestable.
#[derive(Default)]
pub(crate) struct MemStorageContext {
pub struct MemStorageContext {
pub data: RefCell<HashMap<Vec<u8>, Vec<u8>>>,
pub fail_get: Cell<bool>,
pub fail_put: Cell<bool>,
}

impl MemStorageContext {
pub fn new() -> Self {
Self::default()
}

/// Make every subsequent `get` return a storage error.
pub fn fail_reads(&self) {
self.fail_get.set(true);
}

/// Make every subsequent `put` return a storage error.
pub fn fail_writes(&self) {
self.fail_put.set(true);
}

/// Resume normal operation.
pub fn heal(&self) {
self.fail_get.set(false);
self.fail_put.set(false);
}
}

impl<'db> StorageContext<'db> for MemStorageContext {
type Batch = MemBatch;
type RawIterator = MemRawIterator;

fn get<K: AsRef<[u8]>>(&self, key: K) -> CostResult<Option<Vec<u8>>, grovedb_storage::Error> {
if self.fail_get.get() {
return Err(grovedb_storage::Error::StorageError(
"injected read failure".to_string(),
))
.wrap_with_cost(OperationCost::default());
}
Ok(self.data.borrow().get(key.as_ref()).cloned()).wrap_with_cost(OperationCost::default())
}

Expand All @@ -39,6 +71,12 @@ impl<'db> StorageContext<'db> for MemStorageContext {
_children_sizes: ChildrenSizesWithIsSumTree,
_cost_info: Option<KeyValueStorageCost>,
) -> CostResult<(), grovedb_storage::Error> {
if self.fail_put.get() {
return Err(grovedb_storage::Error::StorageError(
"injected write failure".to_string(),
))
.wrap_with_cost(OperationCost::default());
}
self.data
.borrow_mut()
.insert(key.as_ref().to_vec(), value.to_vec());
Expand Down Expand Up @@ -141,7 +179,7 @@ impl<'db> StorageContext<'db> for MemStorageContext {
// ── Batch and RawIterator stubs ───────────────────────────────────────

/// No-op batch (never used — MemStorageContext does immediate writes).
pub(crate) struct MemBatch;
pub struct MemBatch;

impl Batch for MemBatch {
fn put<K: AsRef<[u8]>>(
Expand Down Expand Up @@ -186,7 +224,7 @@ impl Batch for MemBatch {
}

/// Stub iterator (never used by the bulk append tree).
pub(crate) struct MemRawIterator;
pub struct MemRawIterator;

impl RawIterator for MemRawIterator {
fn seek_to_first(&mut self) -> CostContext<()> {
Expand Down
Loading
Loading