Skip to content

Conversation

roberto-bayardo
Copy link
Collaborator

@roberto-bayardo roberto-bayardo commented Jun 29, 2025

  • Allow an empty proof to authenticate an empty MMR.
  • Simplify verification APIs by not requiring the user to provide the end element position, which can be derived from the starting position and the number of elements in the input.
  • Perform more strict validation of the element range provided to verification (elements that fall outside of the MMR range result in error).

@roberto-bayardo roberto-bayardo requested a review from Copilot June 29, 2025 16:54
Copilot

This comment was marked as outdated.

@roberto-bayardo roberto-bayardo marked this pull request as ready for review June 29, 2025 16:56
@roberto-bayardo roberto-bayardo requested a review from danlaine June 29, 2025 16:57
@roberto-bayardo roberto-bayardo force-pushed the handle-empty-range-proving branch 4 times, most recently from da747d2 to 7457abe Compare June 30, 2025 01:02
@roberto-bayardo roberto-bayardo requested a review from Copilot June 30, 2025 01:04
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refines the MMR proof verification API to handle the degenerate case of an empty MMR by removing the need to explicitly provide the end element position and deriving it automatically.

  • Adjusts API functions in Proof to compute end positions from the elements length
  • Introduces a default instance for Proof and updates tests, benches, and related modules accordingly

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
storage/src/mmr/verification.rs API changes in Proof including default implementation and end position derivation
storage/src/mmr/journaled.rs Removed redundant last element position parameter
storage/src/mmr/hasher.rs Updated testing calls to match the new API signature
storage/src/mmr/benches/prove_many_elements.rs Adjusted benchmark calls removing outdated parameters
storage/src/adb/current.rs Updated proof calls to use the new API
storage/src/adb/any.rs Modified proof verification call to align with API changes
Comments suppressed due to low confidence (2)

storage/src/mmr/verification.rs:131

  • [nitpick] Consider adding an inline comment to explain how and why 'end_element_pos' is derived from the number of elements, which may help future maintainers understand this computation.
        };

storage/src/mmr/verification.rs:80

  • [nitpick] Consider adding documentation to the default implementation of Proof to clarify its purpose in handling empty proofs.
impl<D: Digest> Default for Proof<D> {

@roberto-bayardo roberto-bayardo force-pushed the handle-empty-range-proving branch 4 times, most recently from d2d06c2 to a845b8b Compare June 30, 2025 01:10
&self,
hasher: &mut H,
elements: E,
elements: &[E],
Copy link
Contributor

Choose a reason for hiding this comment

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

I think removing end_element_pos makes sense but prefer to keep the IntoIterator for E (makes it much more flexible for elements?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had to remove IntoIterator since in this change we need to know the lenght of the range of elements. And it turned out we didn't rely on that increased flexibillty anywhere.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

(And actually the caller would otherwise need to know the length of the range if they were required to provide the end_offset, so IntoIterator is actually probably not providing any value here.)

return false;
}
};
let end_element_pos = if elements.len() == 1 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can just do leaf_num_to_pos(start_leaf + elements.len() as u64 - 1)? We already handle the case of empty above?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah we could, I was just optimizing away the overhead of leaf_num_to_pos for this "common" case. It's pretty fast operation but it is still log(n). WDYT?

@danlaine
Copy link
Collaborator

Removing end_element_pos makes sense to me, but I'm not sure it makes sense to have a notion of a proof over an empty database. There isn't anything to prove about it. I think it might make more sense for "verify an empty proof" and "verify an empty database" to be undefined.

@roberto-bayardo roberto-bayardo changed the title [storage/mmr] handle degenerate case of proving an MMR is empty [storage/mmr] handle case of proving an MMR is empty Jun 30, 2025
@roberto-bayardo roberto-bayardo force-pushed the handle-empty-range-proving branch from 8ff037f to 66c7413 Compare June 30, 2025 21:28
@roberto-bayardo roberto-bayardo force-pushed the handle-empty-range-proving branch from 2a6b63c to a85644a Compare June 30, 2025 22:17
@patrick-ogrady patrick-ogrady merged commit 31eaf47 into main Jun 30, 2025
28 checks passed
@patrick-ogrady patrick-ogrady deleted the handle-empty-range-proving branch June 30, 2025 23:40
Copy link

codecov bot commented Jun 30, 2025

Codecov Report

Attention: Patch coverage is 97.91667% with 1 line in your changes missing coverage. Please review.

Project coverage is 91.22%. Comparing base (03b535e) to head (1721cec).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
storage/src/adb/current.rs 66.66% 1 Missing ⚠️
@@           Coverage Diff           @@
##             main    #1168   +/-   ##
=======================================
  Coverage   91.21%   91.22%           
=======================================
  Files         216      216           
  Lines       57964    57937   -27     
=======================================
- Hits        52874    52854   -20     
+ Misses       5090     5083    -7     
Files with missing lines Coverage Δ
storage/src/adb/any.rs 99.11% <100.00%> (-0.01%) ⬇️
storage/src/mmr/bitmap.rs 96.70% <100.00%> (ø)
storage/src/mmr/hasher.rs 87.43% <ø> (-0.05%) ⬇️
storage/src/mmr/journaled.rs 98.05% <ø> (-0.01%) ⬇️
storage/src/mmr/verification.rs 95.04% <100.00%> (-0.12%) ⬇️
storage/src/adb/current.rs 96.87% <66.66%> (+0.66%) ⬆️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 03b535e...1721cec. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

3 participants