Skip to content

fix: load full changeset range and add regression test#3945

Merged
jolestar merged 3 commits into
mainfrom
fix/prune-changeset-range-iter
Jan 29, 2026
Merged

fix: load full changeset range and add regression test#3945
jolestar merged 3 commits into
mainfrom
fix/prune-changeset-range-iter

Conversation

@jolestar

Copy link
Copy Markdown
Contributor

Summary

  • replace RocksDB iterator-based changeset range loading with numeric-order batch multi_get to avoid skipping entries encoded in little-endian
  • add regression unit test to ensure a contiguous changeset span is fully returned
  • add tempfile as a dev dependency for the test helper

Testing

  • cargo test -p rooch-store get_changesets_range_returns_full_span

Copilot AI review requested due to automatic review settings January 29, 2026 03:02
@vercel

vercel Bot commented Jan 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
rooch-portal-v2.1 Ready Ready Preview, Comment Jan 29, 2026 5:11am
test-portal Ready Ready Preview, Comment Jan 29, 2026 5:11am
1 Skipped Deployment
Project Deployment Review Updated (UTC)
rooch Ignored Ignored Preview Jan 29, 2026 5:11am

Request Review

@github-actions

github-actions Bot commented Jan 29, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
cargo/tempfile >= 3.0.0, < 4.0.0 🟢 5.7
Details
CheckScoreReason
Code-Review⚠️ 1Found 4/25 approved changesets -- score normalized to 1
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not detected
Maintained🟢 77 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 7
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Vulnerabilities🟢 100 existing vulnerabilities detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection🟢 6branch protection is not maximal on development and all release branches
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • crates/rooch-store/Cargo.toml

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes incorrect loading of state changeset ranges by switching from RocksDB iterator-based scanning (which breaks with little-endian BCS-encoded u64 keys) to a numeric-order multi_get batching strategy, and adds a regression unit test.

Changes:

  • Replace iterator-based range loading with batched multi_get over the numeric [from_order, to_order) span.
  • Add a unit test intended to ensure contiguous changeset spans are fully returned.
  • Add tempfile as a dev-dependency to support RocksDB-backed tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
crates/rooch-store/src/state_store/mod.rs Removes RocksDB iterator logic and always uses batched numeric multi_get; adds RocksDB-backed regression test helper and test.
crates/rooch-store/Cargo.toml Adds tempfile dev-dependency for the new test setup.

Comment on lines +237 to +249
fn temp_state_store() -> StateDBStore {
let dir = TempDir::new().expect("create tempdir");
let registry = Registry::new();
let db = RocksDB::new(
dir.path(),
crate::StoreMeta::get_column_family_names().to_vec(),
RocksdbConfig::default(),
)
.expect("create rocksdb");
let db_metrics = DBMetrics::new(&registry);
let instance = StoreInstance::new_db_instance(db, Arc::new(db_metrics));
StateDBStore::new(instance)
}

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

temp_state_store() drops TempDir at the end of the function, but the returned StateDBStore still holds an open RocksDB instance pointing at that path. This can cause cleanup failures (notably on Windows) and makes the test rely on implementation details of tempfile/filesystem semantics. Keep the temp directory alive for the whole test (e.g., return a struct holding both TempDir and StateDBStore, or create the TempDir in the test and pass dir.path() into a helper).

Copilot uses AI. Check for mistakes.
Comment on lines +255 to +266
// Insert contiguous changesets keyed by numeric order
store.insert_dummy_changesets(110, 30);

// Fetch the span and ensure none are skipped
let got = store
.get_changesets_range_with_limit(110, 140, usize::MAX)
.expect("load range");

assert_eq!(got.len(), 30, "should load all changesets in range");
assert_eq!(got.first().unwrap().0, 110);
assert_eq!(got.last().unwrap().0, 139);
}

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

This test range (110..140) does not reproduce the little-endian RocksDB iterator ordering bug; for many small contiguous values, lexicographic order still matches numeric order, so an iterator-based implementation could still pass this test. To make this a true regression test, choose a span that crosses an endian boundary (e.g., 250..270 crossing 255/256, or 65_530..65_550 crossing 65_535/65_536) so the old iterator approach would deterministically miss entries.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +33
[dev-dependencies]
tempfile = "3"

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

The workspace already pins tempfile (see root Cargo.toml) and other crates depend on it via tempfile = { workspace = true }. Using tempfile = "3" here can lead to version drift across the workspace and duplicate semver requirements. Prefer tempfile = { workspace = true } for consistency.

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

crates/rooch-store/src/state_store/mod.rs:145

  • The doc comment says this is a "Fallback implementation for non-RocksDB stores", but get_changesets_range_with_limit now unconditionally calls this path even for RocksDB. Update the comment (and consider renaming the helper) so it reflects the current behavior.
    /// Fallback implementation for non-RocksDB stores using batch queries
    fn get_changesets_range_batch_fallback(
        &self,

Comment on lines +237 to +249
fn temp_state_store() -> StateDBStore {
let dir = TempDir::new().expect("create tempdir");
let registry = Registry::new();
let db = RocksDB::new(
dir.path(),
crate::StoreMeta::get_column_family_names().to_vec(),
RocksdbConfig::default(),
)
.expect("create rocksdb");
let db_metrics = DBMetrics::new(&registry);
let instance = StoreInstance::new_db_instance(db, Arc::new(db_metrics));
StateDBStore::new(instance)
}

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

temp_state_store() creates a TempDir but drops it at the end of the function, which can delete the underlying directory while the returned StateDBStore/RocksDB is still in use (can lead to flaky failures, especially on Windows). Keep the TempDir alive for the duration of the test (e.g., return (TempDir, StateDBStore) or wrap both in a struct).

Copilot uses AI. Check for mistakes.
@github-actions

Copy link
Copy Markdown

Docker images for this PR are available:

  • ghcr.io/rooch-network/rooch:pr-3945
  • ghcr.io/rooch-network/rooch:pr-3945-5e8fcac

Pull commands:

  • docker pull ghcr.io/rooch-network/rooch:pr-3945
  • docker pull ghcr.io/rooch-network/rooch:pr-3945-5e8fcac

@jolestar jolestar merged commit a543791 into main Jan 29, 2026
29 checks passed
@jolestar jolestar deleted the fix/prune-changeset-range-iter branch January 29, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants