Uh oh!
There was an error while loading. Please reload this page.
fix(grovedb): require proofs to descend to the query path - #7
Merged
Conversation
GroveDB's layered verifier finds the next layer by the proof envelope's lower_layers map key, which is not hash-bound. A prover who renames or drops the entry for a subtree on the query path gets the same root hash with that subtree's results silently gone, so a proof of one value verifies as a proof of absence. check_envelope walks the envelope down every segment of the query path and pins prove_options to the chain default; the ProofVerifier passes the path through.
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
GroveDB's layered verifier looks the next layer up by the proof envelope's
lower_layersmap key, and that key is not hash-bound. A prover who renames or drops the entry for a subtree on the query path gets the same root hash with that subtree's results silently gone — a proof ofK = Vverifies as a proof thatKis absent.check_envelope(proof, expected_path)closes it: the envelope must carry a lower layer for every segment of the query path (once a layer is present its root is hash-bound to the parent), nothing may hang below the path, andprove_options— prover-chosen bytes that steer limit accounting — is pinned to the chain default.VerifyOptions.expected_pathruns it, andGroveDBProofVerifierpasses the path from aPathQueryDatathrough.Testing
test_honest_envelope_descends_to_the_path— a well-formed envelope for[subgroves, aave-v3-lending, indexed, Supply]passes.test_renamed_lower_layer_is_rejected— renaming the entry for a path subtree fails withdoes not descend.test_dropped_lower_layer_is_rejected— dropping the deepest layer fails the same way.test_extra_lower_layers_below_the_path_are_rejected— anything hanging below the queried path is refused.test_non_default_prove_options_is_rejected.test_verify_options_expected_path_invokes_the_guard— wiring:verify_grovedb_proofcalls the guard when a path is set.The guard is tested by constructing the decoded envelope directly, so it does not depend on the byte decoder. Full suite: 305 passed (299 before), 13 skipped.
Why
A client that treats "not in the results" as "absent" would accept a lie of omission from any API server, with a valid root. Requiring the proof to reach the queried path is what makes an empty result at that path a proven absence.
Note (separate, larger issue — not fixed here)
This SDK's proof decoder reads fixed-width (u32 variant, u64 lengths, big-endian) integers, but grovedb 3.1.0 serializes
GroveDBProofwith bincode varint encoding. So the decoder does not parse a real grovedb proof (a real single-key proof reportsversion 4195337), which is why the tests above build the decoded structure directly rather than from real proof bytes. The TypeScript SDK's decoder is varint and does parse real proofs; aligning this one (and the Go/Swift decoders) is a larger follow-up worth its own PR.