chore: bump grovedb to develop (352c2f55)#3656
Conversation
Brings in 4 commits from grovedb develop on top of 7a649386: - #666 Element::NotCountedOrSummed wrapper for combined sum+count opt-out - #667 Element::ReferenceWithSumItem + RefreshReferenceWithSumItem batch op - #668 CI shard cleanup (no platform impact) - #661 Element::ProvableSumTree + AggregateSumOnRange query API-surface fallout adapted in the same commit: - drive: thread new `non_counted: bool` arg through `QualifiedGroveDbOp::refresh_reference_op`. Drive's wrapper still produces plain (counted) references, so the new flag is hard-coded to `false` to preserve prior behavior — non-counted refs and the new `ReferenceWithSumItem` shape are not yet used by platform. - drive: cover the new `TreeType::ProvableSumTree` variant in both `LowLevelDriveOperationTreeTypeConverter::empty_tree_operation_for_known_path_key` and `grove_insert_empty_tree_v0`, using the matching `Element::empty_provable_sum_tree[_with_flags]()` constructor. - rs-sdk-ffi: extend `format_element_data` / `format_element_type` in `system/queries/path_elements.rs` with arms for the three new `Element` variants (`NotCountedOrSummed`, `ReferenceWithSumItem`, `ProvableSumTree`) so the JSON renderer stays exhaustive. - wasm-drive-verify: extend the `QueryItem` match in `state_transition_execution_path_queries::token_transition` with an `AggregateSumOnRange` arm that mirrors the existing `AggregateCountOnRange` "unsupported in token-transition path queries" error, since aggregate range items aren't part of those path queries. `cargo check --workspace --all-features` and `cargo clippy -p drive -p wasm-drive-verify -p rs-sdk-ffi --all-features --no-deps` are clean. The existing `grove_insert_empty_tree` unit tests in rs-drive still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR pins all grovedb-family dependencies across the platform to a new commit (352c2f...) that introduces ProvableSumTree and ReferenceWithSumItem element types. The codebase is extended to support these new variants in empty-tree operations, reference refresh logic, and SDK JSON serialization, with query-type validation added for token-transition paths. ChangesGroveDB Dependency and ProvableSumTree Support
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Review GateCommit:
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/rs-drive/src/util/grove_operations/grove_insert_empty_tree/v0/mod.rs (1)
31-31: ⚡ Quick winAdd a test for the new
ProvableSumTreebranch.The new match arm in Line 31 is not covered by this module’s current tests, so this mapping can regress silently.
Proposed test addition
@@ #[test] + fn test_grove_insert_empty_tree_provable_sum() { + let drive = setup_drive(None); + let pv = PlatformVersion::latest(); + let tx = drive.grove.start_transaction(); + + drive + .grove_insert_empty_tree_v0( + SubtreePath::empty(), + b"provable_sum", + TreeType::ProvableSumTree, + Some(&tx), + None, + &mut vec![], + &pv.drive, + ) + .expect("expected to insert root tree"); + + let mut query_ops = vec![]; + let element = drive + .grove_get_raw( + SubtreePath::empty(), + b"provable_sum", + DirectQueryType::StatefulDirectQuery, + Some(&tx), + &mut query_ops, + &pv.drive, + ) + .expect("expected to get element"); + + assert!( + matches!(element, Some(Element::ProvableSumTree(..))), + "Expected a provable sum tree element after insert" + ); + } + + #[test] fn test_grove_insert_empty_tree_count_sum() {🤖 Prompt for 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. In `@packages/rs-drive/src/util/grove_operations/grove_insert_empty_tree/v0/mod.rs` at line 31, Add a unit test that exercises the new TreeType::ProvableSumTree match arm so it can't regress: call the public function in this module that performs the match (the function containing the TreeType -> Element mapping in grove_insert_empty_tree v0) with TreeType::ProvableSumTree and assert the returned Element equals Element::empty_provable_sum_tree(); place the test alongside the module's other tests (or in the module's #[cfg(test)] tests) so it runs in CI.
🤖 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.
Nitpick comments:
In
`@packages/rs-drive/src/util/grove_operations/grove_insert_empty_tree/v0/mod.rs`:
- Line 31: Add a unit test that exercises the new TreeType::ProvableSumTree
match arm so it can't regress: call the public function in this module that
performs the match (the function containing the TreeType -> Element mapping in
grove_insert_empty_tree v0) with TreeType::ProvableSumTree and assert the
returned Element equals Element::empty_provable_sum_tree(); place the test
alongside the module's other tests (or in the module's #[cfg(test)] tests) so it
runs in CI.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 05fb9d9d-6498-4669-b957-3108dfc6bc44
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
packages/rs-dpp/Cargo.tomlpackages/rs-drive-abci/Cargo.tomlpackages/rs-drive/Cargo.tomlpackages/rs-drive/src/fees/op.rspackages/rs-drive/src/util/grove_operations/grove_insert_empty_tree/v0/mod.rspackages/rs-platform-version/Cargo.tomlpackages/rs-platform-wallet/Cargo.tomlpackages/rs-sdk-ffi/src/system/queries/path_elements.rspackages/rs-sdk/Cargo.tomlpackages/wasm-drive-verify/src/state_transition/state_transition_execution_path_queries/token_transition.rs
The grovedb bump in this PR turned on a stricter proof-envelope decoder (`decode_grovedb_proof_canonical`, introduced alongside the ProvableSumTree / AggregateSumOnRange work in grovedb#661) that rejects any trailing bytes after the bincode envelope. The previous decoder silently tolerated them. Two dash-sdk fixture-replay tests (`test_token_pre_programmed_distributions_present` and `test_token_pre_programmed_distributions_absent`) fail because their recorded proof bytes carry a single legacy trailing byte that the new decoder rejects with "data corruption error: proof has 1 trailing bytes after the encoded envelope". Regenerating those fixtures requires a devnet run (`yarn reset && SDK_TEST_DATA=true yarn start && ./packages/rs-sdk/scripts/generate_test_vectors.sh test_token_pre_programmed_distributions`), so mark both as `#[ignore]` with a note explaining the regen step; production proofs emitted by the bumped drive-abci will not carry the trailing byte, so this is purely fixture rot, not a runtime regression. Also addresses the CodeRabbit nitpick on the `grove_insert_empty_tree_v0` match: add `test_grove_insert_empty_tree_provable_sum` covering the new `TreeType::ProvableSumTree` arm so the mapping cannot regress silently. All 6 tests in the module pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same fixture rot as the dash-sdk tests already ignored in the previous commit: the rs-sdk-ffi integration tests `test_token_pre_programmed_distributions` and `test_token_pre_programmed_distributions_absent` share the proof vectors under `packages/rs-sdk/tests/vectors/`, which the new strict `decode_grovedb_proof_canonical` rejects because of a trailing byte. Mark both as `#[ignore]` with the same regen note. These are the only other tests in the workspace that exercise the `TokenPreProgrammedDistributions` query path; the remaining ~100 fixture-replay tests passed CI cleanly with the bump. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v3.1-dev #3656 +/- ##
============================================
- Coverage 88.07% 88.05% -0.02%
============================================
Files 2521 2521
Lines 308681 308781 +100
============================================
+ Hits 271879 271908 +29
- Misses 36802 36873 +71
🚀 New features to boost your workflow:
|
The grovedb bump turned on the new strict
`decode_grovedb_proof_canonical` (introduced alongside the
ProvableSumTree / AggregateSumOnRange work in grovedb#661) which
rejects any bincode-decoded grovedb proof that leaves trailing bytes
in the input slice. The previous decoder silently tolerated them.
The grovedb docstring itself notes the trailing bytes are
"harmless for the chain-bound correctness guarantee": the decoded
`GroveDBProof` and the root hash it produces are unchanged. Empirically
verified on the failing fixture proof (651 bytes, 1 trailing byte):
the decoder consumes 650 bytes, the decoded value re-encodes byte-for-byte
to those 650 bytes, and `GroveDb::verify_query` on the 650-byte prefix
returns Ok.
Production drive-abci on this grovedb revision emits canonical proofs
(the rs-drive `should_prove_and_verify_*` round-trip tests prove that),
so the strict check would only fire on proofs from older nodes or
recorded fixtures captured against them. That is exactly what broke
the four `test_token_pre_programmed_distributions[_absent]` tests in
dash-sdk and rs-sdk-ffi — they replay legacy proof bytes captured
before grovedb's canonical-encoder fix.
This commit adds a thin backward-compat shim:
- `packages/rs-drive/src/verify/grovedb_proof_compat.rs` exposes
`canonicalize_grovedb_proof(proof: &[u8]) -> Result<Cow<[u8]>, Error>`.
It runs the same bincode decode the new verifier uses, returns the
proof unchanged when it is already canonical (borrow, no alloc), and
trims the prefix bincode actually consumed when trailing bytes are
present. A `tracing::trace!` breadcrumb fires on the trim path so any
remaining source of non-canonical proofs is observable.
- Every `GroveDb::verify_*(proof, ...)` call site in
`packages/rs-drive/src/verify/**` (71 files) is wrapped:
`GroveDb::verify_*(&canonicalize_grovedb_proof(proof)?, ...)`. The
rewrite is mechanical and only touches the proof byte argument; all
other parameters and control flow are unchanged.
Test-internal `GroveDb::verify_query` callers in `rs-drive-abci`'s
query unit tests and `rs-drive/src/prove/...` round-trip helpers are
intentionally not wrapped — they verify proofs they just produced with
the bumped grovedb, so the canonical bytes are guaranteed by
construction.
Verified end-to-end:
- The four previously-failing tests now pass:
`dash-sdk::fetch::tokens::token_pre_programmed_distributions::
{test_token_pre_programmed_distributions_present,_absent}`,
`rs-sdk-ffi::token::{test_token_pre_programmed_distributions,_absent}`.
- All 243 `cargo test -p drive --lib verify` tests pass.
- `cargo check --workspace --all-features` and
`cargo clippy -p drive --features server --no-deps` are clean.
- The shim itself has unit tests covering canonical pass-through,
trailing-byte trimming, and malformed-envelope rejection.
Reverts the `#[ignore]` workarounds applied in the two preceding
commits — those are no longer needed now that the verifier handles
legacy proofs natively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov flagged the new `Element::empty_provable_sum_tree_with_flags` arm in `LowLevelDriveOperationTreeTypeConverter::empty_tree_operation_for_known_path_key` as the only uncovered line in `packages/rs-drive/src/fees/op.rs`. Drive doesn't construct `ProvableSumTree` anywhere outside the matching `grove_insert_empty_tree_v0` arm (which already has a dedicated test), so the converter arm needs its own test. The test calls the trait method with `TreeType::ProvableSumTree` and asserts the resulting `LowLevelDriveOperation` wraps a `GroveOp::InsertOrReplace` carrying an `Element::ProvableSumTree`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…f fixtures
Replaces the verifier-side compat shim (previous commit) with the
simpler fix the user requested: trim the 2 affected fixture files
rather than tolerating non-canonical proofs everywhere.
Background: drive-abci builds older than the grovedb-canonical-encoder
fix emitted grovedb proofs with one harmless trailing byte that
pre-bump grovedb's decoder silently ignored. The new strict
`decode_grovedb_proof_canonical` (grovedb#661) rejects it. The
recorded fixtures for
`test_token_pre_programmed_distributions{_present,_absent}` carry
exactly one such trailing byte (verified empirically: 651 bytes →
650 bytes consumed, re-encoded value matches the 650-byte prefix
exactly, root hash unchanged).
What this commit changes:
- `packages/rs-sdk/tests/vectors/test_token_pre_programmed_distributions_absent/`
trimmed: grovedb_proof 651 → 650 bytes (last byte `1` removed).
- `packages/rs-sdk/tests/vectors/test_token_pre_programmed_distributions_present/`
trimmed: grovedb_proof 1238 → 1237 bytes (last byte `1` removed).
Both fixtures now match exactly what the current drive-abci on this
bumped grovedb produces (proven by the rs-drive
`should_prove_and_verify_pre_programmed_distributions` round-trip
test, which already passes on this branch).
What this commit reverts from the previous fix attempt:
- `packages/rs-drive/src/verify/grovedb_proof_compat.rs` — deleted.
- The `mod grovedb_proof_compat` / `pub use canonicalize_grovedb_proof`
block in `packages/rs-drive/src/verify/mod.rs` — removed.
- 71 verify modules under `packages/rs-drive/src/verify/**` —
unwrapped: `GroveDb::verify_*(&canonicalize_grovedb_proof(proof)?, ...)`
reverted to `GroveDb::verify_*(proof, ...)`, and the helper import
dropped.
The compat shim was overscoped: it added permanent maintenance burden
across 71 call sites for what is effectively a one-time fixture-rot
problem. Production drive-abci on this grovedb revision emits
canonical proofs, so the only place stale proofs could realistically
come from is the cached fixtures themselves — exactly what this fix
now addresses at the source.
Verified:
- `cargo test -p dash-sdk --test main test_token_pre_programmed_distributions`
→ both tests pass.
- `cargo test -p rs-sdk-ffi --tests test_token_pre_programmed_distributions`
→ both tests pass.
- `cargo test -p drive --lib verify --features server` → 240/240 pass
(drops the 3 helper tests removed with the shim).
- `cargo check --workspace --all-features` → clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Issue being fixed or feature implemented
Brings the grovedb dependency up to the latest
develop(352c2f5504fba8795e8ed1056753bfd73c13b4cc) so we can pick up the new sum-tree work and related element/op surface that has landed upstream.HEADof grovedb develop is 4 commits ahead of our previous pin7a649386:feat(grovedb,merk,element): add Element::NotCountedOrSummed wrapper for combined sum+count opt-outfeat(grovedb,element): add Element::ReferenceWithSumItem variant + RefreshReferenceWithSumItem batch opci: drop broken self-hosted macOS runner, run sharded on Ubuntu directly(no platform impact)feat: add Element::ProvableSumTree + AggregateSumOnRange queryWhat was done?
Dependency bump
Updated the
revfor every grovedb-family git dep in the six platformCargo.tomls (rs-drive,rs-drive-abci,rs-sdk,rs-dpp,rs-platform-version,rs-platform-wallet) and refreshedCargo.lockfor all 15 grovedb sub-crates.API-surface adaptations
The bump exposed three breaking API changes that needed thin call-site fixes:
QualifiedGroveDbOp::refresh_reference_opgained anon_counted: boolargument (from grovedb#667).rs-drive's wrapperLowLevelDriveOperation::refresh_reference_for_known_path_key_reference_info(packages/rs-drive/src/fees/op.rs) now passesfalsefor the new flag. Drive's refresh path only ever produces plain (counted) references — the newReferenceWithSumItem/ non-counted shapes aren't used by platform yet — so hard-codingfalsepreserves prior behavior exactly.TreeType::ProvableSumTreevariant added (from grovedb#661).Two exhaustive matches needed a new arm:
LowLevelDriveOperationTreeTypeConverter::empty_tree_operation_for_known_path_key(packages/rs-drive/src/fees/op.rs) andDrive::grove_insert_empty_tree_v0(packages/rs-drive/src/util/grove_operations/grove_insert_empty_tree/v0/mod.rs). Both now route toElement::empty_provable_sum_tree[_with_flags](), mirroring the existingProvableCountTreearms. Each arm gets a dedicated unit test covering the new variant.Three new
Elementvariants (NotCountedOrSummed,ReferenceWithSumItem,ProvableSumTree) added toformat_element_data/format_element_typeinpackages/rs-sdk-ffi/src/system/queries/path_elements.rs, so the JSON renderer fordash_sdk_system_get_path_elementsstays exhaustive.QueryItem::AggregateSumOnRangevariant added (from grovedb#661) — handled inpackages/wasm-drive-verify/src/state_transition/state_transition_execution_path_queries/token_transition.rswith an arm that mirrors the existingAggregateCountOnRange"unsupported in token-transition path queries" error.Proof-fixture trim (
-1 byte× 2 files)Two recorded SDK proof fixtures had to be re-canonicalized after the bump:
GitHub displays them as "Binary file not shown" because the rs-sdk vector format uses a literal
\x00separator between the captured request and response JSONs, which trips git's binary-detection heuristic. The actual change in each fixture is exactly one byte removed from the tail of.version.v0.result.proof.grovedb_proof. The 45-byte file-size delta is purely the JSON re-encoding cost: removing the trailing array element1shortens the inner JSON by 14 chars (,\n 1), and that 14-byte string is then expressed in the outer"Ok":[…]byte array as 14 fewer comma-separated integers (10,32,32,32,32,32,32,32,32,32,32,32,32,49,≈ 45 chars).Why the trailing byte was there
The proofs in those fixtures are
GroveDBProof::V1envelopes (empirically verified: first byte0x01, bincode-decodes asGroveDBProof::V1(LayerProof)consuming all but the trailing byte). V1 proofs first shipped on Dash Platform at protocol v7 (Medusa) via grovedb#513 and apps#3177 — both landed 2026-03-06. At that point V1 had the shape:ProveOptionsis a singlebool(decrease_limit_on_empty_sub_query_result, defaulttrue), which bincode encodes as one byte0x01.On 2026-03-11, grovedb#647 —
fix: remove ProveOptions from V1 proofs to close result-truncation attack— dropped the field. A malicious prover could otherwise set the option totrueeven when the original query specifiedfalse, causing the verifier to consume its result limit faster and return fewer results than actually exist. Removing the field from the wire format meant the verifier now usesProveOptions::default()instead.On 2026-03-14 (3 commits behind #647), apps#3246 (
feat(rs-sdk): implement getTokenPreProgrammedDistributions query) recorded these fixtures against drive-abci built with grovedbdd99ed1d— the pre-#647 V1 shape. Each captured proof therefore carries a single trailing0x01byte that is no longer part of V1's encoded representation.Every grovedb bump since then kept working because the verifier called
bincode::decode_from_slice(proof, config)and silently discarded leftover bytes. The current bump pulls indecode_grovedb_proof_canonical, which rejects any decode that leaves bytes unconsumed — exposing the 8-week-old artifact for the first time.Why trimming is safe
The trailing
ProveOptionsbyte was never bound into the proof's cryptographic state:decode_grovedb_proof_canonical's own docstring describes the trailing-byte tolerance gap as "harmless for the chain-bound correctness guarantee" — the decodedGroveDBProofand the root hash it commits to are unchanged.should_prove_and_verify_pre_programmed_distributionsround-trip test passes against the bumped grovedb, confirming the canonical 650-byte form verifies cleanly with the exact same root hash.bincode::decode_from_slice::<GroveDBProof, _>(proof_651_bytes, config)succeeds, consumes 650 bytes, and re-encoding the decoded value produces byte-for-byte the same 650-byte prefix.The trim brings the cached fixtures in line with what current drive-abci actually emits, so they stay useful as a regression check rather than rotting further with each future grovedb update.
How Has This Been Tested?
dash-sdk::fetch::tokens::token_pre_programmed_distributions::test_token_pre_programmed_distributions_presentdash-sdk::fetch::tokens::token_pre_programmed_distributions::test_token_pre_programmed_distributions_absentrs-sdk-ffimirrors also pass:rs-sdk-ffi::token::test_token_pre_programmed_distributionsrs-sdk-ffi::token::test_token_pre_programmed_distributions_absentcargo test -p drive --lib verify --features server— 240/240 pass (covers every drive-side proof verification path; proves the fixture trim doesn't disturb any other proof).cargo test -p drive --lib util::grove_operations::grove_insert_empty_tree— 6/6 (includes the newProvableSumTreearm).cargo test -p drive --lib fees::op::tests::empty_tree_operation_for_known_path_key_provable_sum_tree— 1/1 (covers the secondProvableSumTreearm; raised patch coverage from 95% to 100% on the new lines).cargo check --workspace --all-featuresandcargo clippy -p drive -p wasm-drive-verify -p rs-sdk-ffi --all-features --no-deps— clean.cargo fmt --allapplied.Breaking Changes
None for platform consumers. The grovedb on-disk encoding for variants that existed in the previous pin is unchanged (the new variants
NotCountedOrSummed=17,ReferenceWithSumItem=18,ProvableSumTree=19were appended). Drive's publicrefresh_reference_for_known_path_key_reference_infowrapper keeps the same signature.Checklist:
For repository code-owners and collaborators only
🤖 Generated with Claude Code