Skip to content

fix(commitment-tree): reject negative sqlite positions#746

Open
thepastaclaw wants to merge 2 commits into
dashpay:developfrom
thepastaclaw:fix-sqlite-negative-positions
Open

fix(commitment-tree): reject negative sqlite positions#746
thepastaclaw wants to merge 2 commits into
dashpay:developfrom
thepastaclaw:fix-sqlite-negative-positions

Conversation

@thepastaclaw

@thepastaclaw thepastaclaw commented May 23, 2026

Copy link
Copy Markdown
Contributor

PR Body

Summary

  • Reject negative SQLite shard_index and position values when reading
    legacy commitment tree rows.
  • Add non-negative CHECK constraints for newly-created SQLite commitment
    tree tables.
  • Cover schema rejection and legacy corrupt-row handling for shards,
    checkpoints, and marks-removed positions.

Validation

  • cargo fmt --all
  • git diff --check
  • cargo check --offline -p grovedb-commitment-tree --features sqlite
  • cargo test --offline -p grovedb-commitment-tree --features sqlite \ client::sqlite_store_tests -- --nocapture — 32 passed
  • Pre-PR code review gate: ship

Summary by CodeRabbit

  • Bug Fixes
    • Added stricter validation for local stored shard and checkpoint data to block negative values from affecting shard indexing and checkpoint state.
    • Enforced non-negative constraints at the database level for key numeric fields, while preserving expected support for null checkpoint positions.
    • Improved error handling when loading corrupted legacy data containing invalid negative values.
  • Tests
    • Added comprehensive SQLite and legacy-schema tests to confirm negative inserts are rejected and corrupted rows surface clear failures.

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dc09f909-64b0-42dc-8310-a2bb62843ff7

📥 Commits

Reviewing files that changed from the base of the PR and between cd1aafd and 851f1da.

📒 Files selected for processing (2)
  • grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
  • grovedb-commitment-tree/src/client/sqlite_store_tests.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • grovedb-commitment-tree/src/client/sqlite_store_tests.rs
  • grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs

📝 Walkthrough

Walkthrough

This PR strengthens SQLite data integrity by validating that shard indices and checkpoint positions are non-negative. It introduces a validation helper, applies CHECK constraints to database schemas, updates retrieval methods to use validation, and verifies the changes with schema-level and integration tests.

Changes

Negative Value Validation for Shard and Checkpoint Operations

Layer / File(s) Summary
Validation helper and schema constraints
grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
Adds non_negative_i64_to_u64 helper that returns SqliteShardStoreError::Serialization on negative values. Adds CHECK (shard_index >= 0) to commitment_tree_shards and CHECK constraints to checkpoint-related position columns (allowing NULL for checkpoint positions).
Shard index validation in retrieval operations
grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
Updates sql_last_shard and sql_get_shard_roots to validate shard_index as i64 and convert via the helper before constructing Address values, replacing direct unchecked casting to u64.
Checkpoint position validation during load
grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
Updates sql_load_checkpoint to validate non-negative positions for both TreeState::AtPosition and each marks_removed entry via the helper; refactors marks construction from collect to explicit BTreeSet loop insertion.
Test infrastructure and schema constraint validation
grovedb-commitment-tree/src/client/sqlite_store_tests.rs
Adds legacy_schema_conn() helper defining legacy table schemas. Schema-level tests verify SQLite rejects negative shard_index, negative checkpoint position, and negative mark position inserts via CHECK constraints, while accepting NULL checkpoint positions.
Shard error path integration tests
grovedb-commitment-tree/src/client/sqlite_store_tests.rs
Integration tests seed corrupted legacy commitment_tree_shards with negative shard_index and assert last_shard() and get_shard_roots() return errors containing "invalid negative shard_index in sqlite row: -1".
Checkpoint error path integration tests
grovedb-commitment-tree/src/client/sqlite_store_tests.rs
Integration tests seed corrupted legacy checkpoint rows with negative position values and assert get_checkpoint() returns errors containing "invalid negative position in sqlite row: -1" for both checkpoint and mark-removed rows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰 A validation helper hops into the scene,
Checking for negatives—nasty and mean!
SQLite constraints guard with a CHECK,
No more surprises, our data's in deck!
Errors caught early, our queries run clean. 🌳

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main change: adding validation to reject negative SQLite positions in the commitment tree module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@thepastaclaw

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs`:
- Around line 128-134: Wrap rusqlite errors from both stmt.query_map calls and
their row iterations with contextual mapping using .map_err(|e|
Error::CorruptedData(format!("...: {}", e))) so callers get operation-specific
context; specifically, update the first loop around stmt.query_map(...) that
constructs Address::from_parts(Level::from(SHARD_HEIGHT),
non_negative_i64_to_u64("shard_index", index?)?) to map any query_map/row error
into Error::CorruptedData with a message like "querying shard indices" and do
the same for the second query_map loop at the other location (lines ~393-399)
with a descriptive message for that operation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d0757e2e-a0d6-4211-9377-70c0dca97249

📥 Commits

Reviewing files that changed from the base of the PR and between 9f67e8c and cd1aafd.

📒 Files selected for processing (2)
  • grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
  • grovedb-commitment-tree/src/client/sqlite_store_tests.rs

Comment thread grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs
@codecov

codecov Bot commented May 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.43%. Comparing base (9f67e8c) to head (851f1da).
⚠️ Report is 10 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop     #746   +/-   ##
========================================
  Coverage    91.43%   91.43%           
========================================
  Files          236      236           
  Lines        67111    67120    +9     
========================================
+ Hits         61364    61373    +9     
  Misses        5747     5747           
Components Coverage Δ
grovedb-core 88.94% <ø> (ø)
merk 92.26% <ø> (ø)
storage 86.36% <ø> (ø)
commitment-tree 96.46% <100.00%> (+0.02%) ⬆️
mmr 96.79% <ø> (ø)
bulk-append-tree 89.39% <ø> (ø)
element 97.38% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@thepastaclaw thepastaclaw force-pushed the fix-sqlite-negative-positions branch from cd1aafd to 5ca122d Compare May 23, 2026 20:01
@thepastaclaw

thepastaclaw commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

✅ Review complete (commit 851f1da)

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Code Review

Small, well-scoped defensive PR for the SQLite commitment-tree store: adds CHECK constraints to freshly created tables and validates legacy i64 rows on read before converting to u64. Read coverage spans the natural enumeration paths (sql_last_shard, sql_get_shard_roots, checkpoint loads, mark loads) and the test suite exercises both schema-level rejection and legacy-row rejection. No in-scope blockers or suggestions found.

Note: GitHub does not allow PastaClaw to approve their own PR, so this clean review is posted as a comment review rather than an approval.

Out-of-scope follow-up noted

  • Write-side u64 as i64 casts and direct sql_get_shard index cast remain unchecked — Multiple write paths (sql_put_shard:114, sql_truncate_shards:146, sql_add_checkpoint:213,224, sql_update_checkpoint_with:323,333) and the targeted read path sql_get_shard:57 still use unchecked as i64 casts on u64 values. On the new schema the added CHECK constraints reject these defensively at write time; on legacy schemas a wrapped negative could be written. Pre-existing pattern, not introduced by this PR. The PR's read-side guarantee is enforced where shards/checkpoints are enumerated, which is the realistic legacy-data exposure path. A direct get_shard(addr) whose index wraps to a negative would require a contrived caller. Worth tracking separately to apply i64::try_from(u64) symmetrically at the write boundary and the index-bind in sql_get_shard.
    • Follow-up: Open a follow-up issue to use i64::try_from(u64) for shard_index and position values at the write boundary and the sql_get_shard query bind in grovedb-commitment-tree/src/client/sqlite_store/sql_helpers.rs.

@thepastaclaw thepastaclaw marked this pull request as ready for review June 16, 2026 00:56
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.

1 participant