Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tree): Return membership-proof when getting tree values #136

Merged
merged 10 commits into from
Oct 9, 2024

Conversation

jns-ps
Copy link
Contributor

@jns-ps jns-ps commented Oct 8, 2024

Introduces a new response structure for hashchain retrieval, that returns the corresponding membership-proofs along with the hashchain

Summary by CodeRabbit

  • New Features

    • Introduced a new response structure for hashchain retrieval, enhancing error handling and response clarity.
    • Added MembershipProof and HashchainResponse types for improved data management.
    • Updated UserKeyResponse to include an optional hashchain field and a new proof type.
  • Bug Fixes

    • Streamlined error handling in various methods related to hashchain processing.
  • Documentation

    • Updated method signatures and structures to reflect new response handling and types.

jns-ps added 4 commits October 8, 2024 10:21
Before this, only a non-membership-proof was returned when the value could not be found in the tree. Now, a proof is returned alongside the value when it can be found.
Copy link

vercel bot commented Oct 8, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
prism ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 9, 2024 7:26am

Copy link
Contributor

coderabbitai bot commented Oct 8, 2024

Walkthrough

The changes introduce a new type, HashchainResponse, to improve error handling and response management in various components of the codebase. The update_account function now uses pattern matching with HashchainResponse::Found instead of direct unwrapping. Additionally, a new struct, MembershipProof, is added, and several method signatures are updated to return HashchainResponse. The modifications affect the tree, sequencer, and webserver modules, enhancing the overall structure and error management across the system.

Changes

File Path Change Summary
crates/common/src/test_utils.rs Added HashchainResponse to use statement; updated update_account and create_random_update for new response handling.
crates/common/src/tree.rs Introduced MembershipProof struct and HashchainResponse enum; modified get, insert, and update methods to use new response structure.
crates/prism/src/node_types/sequencer.rs Updated Sequencer methods to use HashchainResponse; changed get_hashchain return type and logic for error management.
crates/prism/src/webserver.rs Modified UserKeyResponse to include SparseMerkleProof and an optional hashchain; refactored get_hashchain to utilize HashchainResponse.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WebServer
    participant Sequencer
    participant Tree

    User->>WebServer: Request hashchain
    WebServer->>Sequencer: Call get_hashchain
    Sequencer->>Tree: Call get with key
    Tree-->>Sequencer: Return HashchainResponse
    Sequencer-->>WebServer: Return HashchainResponse
    WebServer-->>User: Respond with hashchain
Loading

🐰 "In the code, a change took flight,
With HashchainResponse, oh what a sight!
Errors now handled with care,
MembershipProof joins the fair.
A hop, a skip, through trees we weave,
In this new structure, we believe!" 🐇

Possibly related PRs

  • feat(sp1): hashchain signature verification in sp1 circuit #125: The changes in this PR involve modifications to the Hashchain implementation, including the introduction of new methods for validating and managing hashchain entries, which are directly related to the enhancements made in the main PR regarding the HashchainResponse type and its usage in error handling and retrieval processes.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (5)
crates/prism/src/node_types/sequencer.rs (2)

Line range hint 365-372: LGTM: Improved get_hashchain method signature and implementation.

The change to return Result<HashchainResponse> simplifies the method and aligns with the new HashchainResponse type. This improvement enhances code clarity and maintainability.

Consider adding a brief comment explaining the HashchainResponse type for better documentation:

 pub async fn get_hashchain(&self, id: &String) -> Result<HashchainResponse> {
+    // Returns a HashchainResponse which can be either Found(Hashchain, Proof) or NotFound(NonMembershipProof)
     let tree = self.tree.read().await;
     let hashed_id = Digest::hash(id);
     let key_hash = KeyHash::with::<Hasher>(hashed_id);

     tree.get(key_hash)
 }

392-398: LGTM: Enhanced error handling in validate_and_queue_update.

The use of pattern matching with HashchainResponse::Found and the bail! macro improves error handling and code robustness. This change aligns well with the PR objectives.

Consider using anyhow::ensure! for a more idiomatic error handling:

-                let HashchainResponse::Found(mut hc, _) = hcr else {
-                    bail!("Hashchain not found for id: {}", incoming_operation.id())
-                };
+                let (mut hc, _) = hcr.found().context(format!("Hashchain not found for id: {}", incoming_operation.id()))?;

This change provides more context in the error message and uses the ? operator for concise error propagation.

crates/prism/src/webserver.rs (3)

56-57: Update UserKeyResponse documentation to reflect new structure

The UserKeyResponse struct has been modified to include an optional hashchain:

pub struct UserKeyResponse {
    pub hashchain: Option<Hashchain>,
    pub proof: SparseMerkleProof<Hasher>,
}

Ensure that the API documentation and any related comments are updated to reflect that hashchain can be None. This helps clients understand the possible values and handle them appropriately.


162-178: Consider unifying response status codes for better client experience

Currently, the Found case returns StatusCode::OK, while the NotFound case returns an error status code. Since both cases return a UserKeyResponse, consider always returning StatusCode::OK and using the hashchain field being Some or None to indicate presence or absence. This approach can simplify client-side error handling.

Apply this diff if you choose to return StatusCode::OK for both cases:

 HashchainResponse::NotFound(non_membership_proof) => (
-    StatusCode::NOT_FOUND,
+    StatusCode::OK,
     Json(UserKeyResponse {
         hashchain: None,
         proof: non_membership_proof.proof,
     }),
 )
     .into_response(),

149-159: Handle potential panics when unwrapping errors

In the error handling block, get_hashchain_result.unwrap_err() is used to retrieve the error message. If get_hashchain_result is Ok, calling unwrap_err() will cause a panic. However, since you're already in the Err case, this is safe. Ensure that this pattern is consistently safe in all similar contexts.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b895f4e and 1840de6.

📒 Files selected for processing (4)
  • crates/common/src/test_utils.rs (2 hunks)
  • crates/common/src/tree.rs (12 hunks)
  • crates/prism/src/node_types/sequencer.rs (3 hunks)
  • crates/prism/src/webserver.rs (3 hunks)
🧰 Additional context used
🔇 Additional comments (8)
crates/prism/src/node_types/sequencer.rs (3)

1-1: LGTM: Import changes enhance error handling and response management.

The addition of bail and HashchainResponse to the imports suggests improvements in error handling and hashchain response management. These changes align well with the PR objectives.

Also applies to: 5-7


Line range hint 1-600: Summary: Improved error handling and response management

The changes in this file enhance error handling and introduce a new HashchainResponse type, improving the overall robustness and clarity of the code. The modifications align well with the PR objectives of including proof in the WS response.

Key improvements:

  1. Addition of bail! for more concise error handling.
  2. Introduction of HashchainResponse for better management of hashchain responses.
  3. Updated method signatures and implementations to use the new HashchainResponse type.

Suggestions for further improvement:

  1. Add brief comments explaining the HashchainResponse type for better documentation.
  2. Consider using anyhow::ensure! for more idiomatic error handling in some cases.
  3. Review and update test cases to cover the new behavior and error cases.

Overall, these changes represent a positive step towards more robust and maintainable code.


Line range hint 409-600: Consider updating test cases to reflect recent changes.

While the main code has been updated to use HashchainResponse and improved error handling, the test cases haven't been modified. It's important to ensure that the tests cover the new behavior and error cases.

To verify the test coverage, you can run the following script:

Please review the output and consider adding or updating tests to cover the new HashchainResponse type and error handling mechanisms.

crates/prism/src/webserver.rs (1)

162-169: Ensure consistent handling of optional hashchain in responses

In the HashchainResponse::Found case, hashchain is wrapped in Some, and in the NotFound case, it's None. Ensure that any clients consuming this API properly handle the optional hashchain field. This change might require updates to client-side code and documentation to prevent None value misinterpretation.

Run the following script to identify usages of UserKeyResponse in the codebase:

✅ Verification successful

Consistent handling of hashchain in UserKeyResponse verified

All instances of UserKeyResponse correctly handle the optional hashchain field as Some or None.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of UserKeyResponse to verify proper handling of optional hashchain

# Expected: All usages handle hashchain being None or Some.

rg --type rust 'UserKeyResponse' -A 5 -g '!webserver.rs'

Length of output: 56


Script:

#!/bin/bash
# Description: Verify that all usages of UserKeyResponse handle the optional hashchain field appropriately.

# Use ast-grep to find all instances of UserKeyResponse and inspect the hashchain field handling
ast-grep --lang rust --pattern 'UserKeyResponse { hashchain: $_, proof: $_ }' .

Length of output: 630

crates/common/src/test_utils.rs (1)

4-4: Importing HashchainResponse is appropriate

The addition of HashchainResponse to the import statement is necessary for handling the tree responses effectively.

crates/common/src/tree.rs (3)

191-204: Code looks good for MembershipProof

The implementation of the MembershipProof struct and its verify method appears correct and follows best practices.


692-696: No issues found with non-membership proof verification

The test for getting a non-existing key correctly handles the NotFound response and verifies the non-membership proof.


828-835: Tests look good for verifying multiple inserts

The test test_batch_writing appropriately checks the insertion and retrieval of multiple accounts using the updated HashchainResponse.

crates/prism/src/webserver.rs Outdated Show resolved Hide resolved
crates/prism/src/webserver.rs Outdated Show resolved Hide resolved
crates/common/src/test_utils.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@distractedm1nd distractedm1nd left a comment

Choose a reason for hiding this comment

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

beautiful, king 👑

crates/common/src/test_utils.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/prism/src/node_types/sequencer.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/prism/src/webserver.rs Show resolved Hide resolved
crates/prism/src/webserver.rs Outdated Show resolved Hide resolved
crates/prism/src/webserver.rs Outdated Show resolved Hide resolved
When no value is found within /get-hashchain, there is still a valid non-membership-proof response. In order not to confuse clients that may think a non-success code means a failed request, we switch to a success code here. Clients have to parse the hashchain property to see if there is a valid value.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (8)
crates/prism/src/webserver.rs (1)

149-159: LGTM: Improved error handling, with a minor suggestion

The error handling has been improved:

  1. The use of let Ok(...) = ... else syntax simplifies the logic.
  2. The status code change to INTERNAL_SERVER_ERROR is appropriate for server-side errors.

However, consider making the error message more specific:

- "Couldn't get hashchain: {}",
+ "Failed to retrieve hashchain or non-inclusion proof: {}",

This change would provide more context about the nature of the error.

crates/prism/src/node_types/sequencer.rs (3)

Line range hint 366-373: LGTM: Improved get_hashchain method with simplified return type.

The updated get_hashchain method now returns Result<HashchainResponse>, which aligns with the new HashchainResponse type and simplifies error handling. The implementation is more concise and directly returns the result of tree.get(key_hash).

Consider adding a brief comment explaining the purpose of KeyHash::with::<Hasher>(hashed_id) for better code documentation:

 pub async fn get_hashchain(&self, id: &String) -> Result<HashchainResponse> {
     let tree = self.tree.read().await;
     let hashed_id = Digest::hash(id);
+    // Create a KeyHash using the custom Hasher for consistent key representation
     let key_hash = KeyHash::with::<Hasher>(hashed_id);

     tree.get(key_hash)
 }

393-399: LGTM: Improved error handling and pattern matching in validate_and_queue_update.

The updated validate_and_queue_update method now uses pattern matching with HashchainResponse::Found, which is more idiomatic and aligns with the new HashchainResponse type. The error handling has been improved using bail!, enhancing readability and consistency with the added import.

Consider using a more descriptive variable name for the hashchain response:

-let hc_response = self.get_hashchain(&incoming_operation.id()).await?;
+let hashchain_response = self.get_hashchain(&incoming_operation.id()).await?;

-let Found(mut hc, _) = hc_response else {
+let Found(mut hashchain, _) = hashchain_response else {
     bail!("Hashchain not found for id: {}", incoming_operation.id())
 };

-hc.perform_operation(incoming_operation.clone())?;
+hashchain.perform_operation(incoming_operation.clone())?;

This change improves code readability and aligns with the previous review comment suggesting the use of hashchain_response instead of hcr.


Line range hint 412-599: Consider adding test cases for new error handling and pattern matching.

While the existing test cases cover the main functionality of the Sequencer struct, it would be beneficial to add new test cases that specifically target the updated error handling and pattern matching in the validate_and_queue_update method. This will ensure that the new changes are thoroughly tested.

Consider adding the following test cases:

  1. Test the case where get_hashchain returns a NotFound response.
  2. Test the case where perform_operation fails and triggers the bail! error.

Example:

#[tokio::test]
async fn test_validate_and_queue_update_hashchain_not_found() {
    let sequencer = create_test_sequencer().await;
    
    // Create an operation that requires an existing hashchain
    let signing_key = create_mock_signing_key();
    let add_key_op = Operation::new_add_key(
        "non_existent@example.com".to_string(),
        signing_key.verifying_key(),
        &signing_key,
        0,
    ).unwrap();

    // Attempt to validate and queue the update
    let result = sequencer.clone().validate_and_queue_update(&add_key_op).await;

    // Assert that the operation failed due to hashchain not found
    assert!(result.is_err());
    assert!(result.unwrap_err().to_string().contains("Hashchain not found"));
}

This will help ensure that the new error handling and pattern matching logic is working as expected.

crates/common/src/tree.rs (4)

24-25: Consider using explicit imports instead of wildcard import

While using use HashchainResponse::*; can make the code more concise, it's generally considered better practice to use explicit imports. This helps avoid potential naming conflicts and improves code readability by making it clear which items are being used from the HashchainResponse enum.

Consider replacing the wildcard import with explicit imports of the enum variants you're using, like this:

-use HashchainResponse::*;
+use HashchainResponse::{Found, NotFound};

This change will make the code more explicit about which parts of HashchainResponse are being used.


289-297: LGTM: Well-designed HashchainResponse enum with a minor suggestion

The new HashchainResponse enum is well-designed and clearly represents the possible outcomes of a hashchain lookup. The use of MembershipProof and NonMembershipProof in the variants provides additional verification capabilities, which is a good practice.

Consider adding a brief doc comment for the enum itself, explaining its purpose and when it's used. For example:

/// Represents the result of a hashchain lookup operation.
/// This enum is returned by the `get` method of the `SnarkableTree` trait.
#[derive(Debug)]
pub enum HashchainResponse {
    // ... existing variants ...
}

This additional documentation will provide more context for developers using this enum.


382-394: LGTM: Improved error handling with a minor optimization suggestion

The changes to the process_operation method improve error handling by using pattern matching on HashchainResponse. This approach is more robust and aligns well with the new HashchainResponse enum.

Consider avoiding the unnecessary clone() of the operation:

 match self.get(key_hash)? {
     HashchainResponse::Found(mut current_chain, _) => {
-        let new_entry = current_chain.perform_operation(operation.clone())?;
+        let new_entry = current_chain.perform_operation(operation)?;
         debug!("updating hashchain for user id {}", id.clone());
-        let proof = self.update(key_hash, new_entry.clone())?;
+        let proof = self.update(key_hash, new_entry)?;
         Ok(Proof::Update(proof))
     }
     HashchainResponse::NotFound(_) => {
         bail!("Failed to get hashchain for ID {}", id)
     }
 }

This change assumes that perform_operation and update can work with references to Operation and HashchainEntry respectively. If they can't, please disregard this suggestion.


553-576: LGTM with optimization suggestion

The changes to the get method look good. The new return type HashchainResponse simplifies the method signature and aligns well with the new HashchainResponse enum. The logic for creating MembershipProof and NonMembershipProof is correct.

To optimize performance, consider retrieving the current root hash once at the beginning of the method instead of calling self.get_current_root()? multiple times:

 fn get(&self, key: KeyHash) -> Result<HashchainResponse> {
+    let root = self.get_current_root()?.into();
     let (value, proof) = self.jmt.get_with_proof(key, self.epoch)?;

     match value {
         Some(serialized_value) => {
             let deserialized_value = Self::deserialize_value(&serialized_value)?;
             let membership_proof = MembershipProof {
-                root: self.get_current_root()?.into(),
+                root: root.clone(),
                 proof,
                 key,
                 value: deserialized_value.clone(),
             };
             Ok(HashchainResponse::Found(
                 deserialized_value,
                 membership_proof,
             ))
         }
         None => {
             let non_membership_proof = NonMembershipProof {
-                root: self.get_current_root()?.into(),
+                root,
                 proof,
                 key,
             };
             Ok(HashchainResponse::NotFound(non_membership_proof))
         }
     }
 }

This change reduces the number of calls to get_current_root() from two to one, potentially improving performance, especially if get_current_root() is an expensive operation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1840de6 and 91bcfc6.

📒 Files selected for processing (4)
  • crates/common/src/test_utils.rs (2 hunks)
  • crates/common/src/tree.rs (13 hunks)
  • crates/prism/src/node_types/sequencer.rs (3 hunks)
  • crates/prism/src/webserver.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/common/src/test_utils.rs
🧰 Additional context used
🔇 Additional comments (7)
crates/prism/src/webserver.rs (4)

14-19: LGTM: Import changes reflect updated dependencies

The new import of SparseMerkleProof and the updated imports from prism_common align with the changes in the code structure and types being used.


56-57: LGTM: UserKeyResponse struct updated to handle not found cases

The changes to the UserKeyResponse struct are well-considered:

  1. Option<Hashchain> allows for explicit representation of cases where a hashchain is not found.
  2. SparseMerkleProof<Hasher> aligns with the new proof type being used.

These changes improve the flexibility and expressiveness of the response structure.


161-176: LGTM: Improved response handling for found and not found cases

The new structure for handling responses is well-implemented:

  1. Explicit handling of HashchainResponse::Found and HashchainResponse::NotFound cases improves clarity.
  2. Consistent use of StatusCode::OK for both cases is appropriate, as both return valid responses (either with a hashchain or a non-membership proof).
  3. The response structure is consistent, using Some(hashchain) or None as appropriate.

This implementation aligns well with the previous discussions and improves the overall response handling.


Line range hint 1-200: Overall LGTM: Improved error handling and response structure

The changes in this file significantly improve the handling of hashchain retrieval and proof management:

  1. The UserKeyResponse struct now accommodates both found and not found scenarios.
  2. Error handling in the get_hashchain function is more robust and uses appropriate status codes.
  3. The response structure for both found and not found cases is consistent and informative.
  4. The changes align well with previous review comments and suggestions.

These improvements enhance the clarity, flexibility, and reliability of the webserver's hashchain-related operations.

crates/prism/src/node_types/sequencer.rs (2)

1-1: LGTM: Import updates enhance error handling and align with tree structure changes.

The addition of bail from anyhow and the updated imports from prism_common::tree reflect improvements in error handling and changes to the tree-related structures. These modifications are consistent with the overall changes in the file.

Also applies to: 5-8


Line range hint 1-599: Overall improvements in error handling and type consistency.

The changes in this file primarily focus on enhancing error handling and aligning the code with the new HashchainResponse type. These modifications improve the overall robustness and readability of the Sequencer implementation. The core functionality remains intact while benefiting from more idiomatic Rust patterns and clearer error management.

Key improvements:

  1. Updated imports to include bail and new tree-related types.
  2. Simplified get_hashchain method with a more consistent return type.
  3. Enhanced validate_and_queue_update with better pattern matching and error handling.

These changes contribute to a more maintainable and error-resistant codebase. Consider addressing the minor suggestions in the previous comments and adding the proposed test cases to further strengthen the implementation.

crates/common/src/tree.rs (1)

192-206: LGTM: Well-designed MembershipProof struct and implementation

The new MembershipProof struct and its implementation look well-designed and correctly implemented. The struct contains all necessary fields for a membership proof, and the verify method properly serializes the value and verifies the existence of the proof.

crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (5)
crates/prism/src/webserver.rs (2)

56-57: LGTM: UserKeyResponse struct changes are appropriate.

The changes to the UserKeyResponse struct, including making hashchain optional and updating the proof type, align with the new functionality.

Consider updating the struct's documentation to reflect these changes, especially explaining when hashchain might be None and the implications of using SparseMerkleProof<Hasher>.


Line range hint 1-200: Overall improvements to webserver functionality and error handling.

The changes in this file significantly enhance the webserver's functionality and error handling:

  1. The UserKeyResponse struct now accommodates both found and not found scenarios.
  2. Error handling in the get_hashchain function is more robust and informative.
  3. The response structure for the get_hashchain endpoint is now consistent, returning StatusCode::OK for both found and not found cases, which aligns with RESTful best practices.

These improvements contribute to a more reliable and maintainable codebase. The changes effectively address the concerns raised in previous reviews and align with the stated PR objectives.

Consider adding unit tests to verify the new behavior of the get_hashchain function, especially focusing on the different HashchainResponse scenarios and error handling.

crates/prism/src/node_types/sequencer.rs (3)

Line range hint 366-373: LGTM: Simplified get_hashchain method improves API consistency.

The return type change to Result<HashchainResponse> simplifies the API and likely improves error handling. The implementation is now more concise, delegating the creation of HashchainResponse to the tree implementation.

Consider adding a brief comment explaining the purpose of KeyHash::with::<Hasher>(hashed_id) for better code documentation.


393-399: LGTM: Improved error handling in validate_and_queue_update.

The use of pattern matching with HashchainResponse::Found and the bail! macro enhances error handling and makes the code more robust. This change aligns well with Rust best practices.

Consider using a more descriptive variable name than hc for better readability, e.g., hashchain.


Impact Detected in webserver.rs Due to get_hashchain Changes

The get_hashchain method is utilized in crates/prism/src/webserver.rs for defining routes and handling asynchronous requests. Changes to its return type or behavior in sequencer.rs may affect the functionality within the webserver.

  • Affected File:
    • crates/prism/src/webserver.rs
      • Route definitions: /get-hashchain
      • Asynchronous calls handling get_hashchain results

Please review and update the webserver.rs implementations to ensure compatibility with the updated HashchainResponse.

🔗 Analysis chain

Line range hint 366-399: Verify impact of HashchainResponse changes on the wider system.

The introduction of HashchainResponse and the related changes in error handling improve the robustness of the Sequencer. However, it's important to ensure that these changes are compatible with other parts of the system that interact with the Sequencer.

Run the following script to check for potential impacts:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for uses of old return types or methods that might be affected by the HashchainResponse changes.

# Test: Search for potential uses of old return types or affected methods
rg --type rust 'Result<Result<Hashchain, NonMembershipProof>>' -g '!crates/prism/src/node_types/sequencer.rs'
rg --type rust 'get_hashchain' -g '!crates/prism/src/node_types/sequencer.rs'

Length of output: 691

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 91bcfc6 and c908596.

📒 Files selected for processing (4)
  • crates/common/src/test_utils.rs (2 hunks)
  • crates/common/src/tree.rs (13 hunks)
  • crates/prism/src/node_types/sequencer.rs (3 hunks)
  • crates/prism/src/webserver.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/common/src/test_utils.rs
🧰 Additional context used
🔇 Additional comments (5)
crates/prism/src/webserver.rs (3)

14-19: LGTM: Import changes are appropriate.

The new imports for SparseMerkleProof and prism_common types are correctly added and align with the changes made in the file.


149-159: LGTM: Improved error handling in get_hashchain.

The changes to error handling are well-implemented:

  1. The use of let Ok(...) = ... else syntax improves readability.
  2. The error message is more descriptive and accurate.
  3. Using StatusCode::INTERNAL_SERVER_ERROR is appropriate for server-side errors.

These changes effectively address the concerns raised in previous review comments.


161-176: LGTM: Consistent handling of HashchainResponse.

The changes to handle HashchainResponse are well-implemented:

  1. Both Found and NotFound cases return StatusCode::OK, addressing the previous discussion about returning success status codes.
  2. The NotFound case correctly returns a UserKeyResponse with hashchain: None.
  3. The implementation maintains a consistent response structure while distinguishing between found and not found cases.

These changes improve the API's consistency and align with best practices for RESTful endpoints.

crates/prism/src/node_types/sequencer.rs (2)

1-1: LGTM: Import updates enhance error handling and align with module changes.

The addition of bail to the anyhow import and the updates to prism_common::tree imports, particularly HashchainResponse, reflect improvements in error handling and alignment with changes in the tree module.

Also applies to: 5-7


393-393: Past suggestion implemented: Variable naming improved.

The code now uses hc_response instead of hcr, as suggested in a previous review. This change enhances code readability.

crates/common/src/tree.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps changed the title Include proof in ws response feat(tree): Return membership-proof when getting tree values Oct 8, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (7)
crates/prism/src/node_types/sequencer.rs (2)

Line range hint 366-373: LGTM: Simplified get_hashchain method.

The updated method signature and implementation improve clarity by using HashchainResponse. This change aligns well with the new imports and simplifies error handling.

Consider adding a brief comment explaining the HashchainResponse type for better documentation:

 pub async fn get_hashchain(&self, id: &String) -> Result<HashchainResponse> {
+    // HashchainResponse can be Found(Hashchain, MembershipProof) or NotFound(NonMembershipProof)
     let tree = self.tree.read().await;
     let hashed_id = Digest::hash(id);
     let key_hash = KeyHash::with::<Hasher>(hashed_id);

     tree.get(key_hash)
 }

393-399: LGTM: Improved error handling in validate_and_queue_update.

The use of pattern matching with HashchainResponse::Found and the bail! macro enhances error handling and aligns with Rust best practices.

Consider using a more descriptive error message:

-                    bail!("Hashchain not found for id: {}", incoming_operation.id())
+                    bail!("Cannot perform operation: Hashchain not found for id '{}'", incoming_operation.id())
crates/common/src/tree.rs (5)

24-25: Consider using explicit imports instead of wildcard import

While using use HashchainResponse::*; can make the code more concise, it's generally considered better practice to use explicit imports. This helps prevent potential naming conflicts and makes the code more readable by clearly showing which variants are being used.

Consider changing this to explicitly import the variants you need, like this:

-use HashchainResponse::*;
+use HashchainResponse::{Found, NotFound};

192-206: LGTM! Consider adding documentation

The MembershipProof struct and its implementation look good. The verify method correctly serializes the value and verifies its existence using the proof.

Consider adding documentation comments to the struct and its method to improve code readability and maintainability. For example:

/// Represents a proof of membership for a hashchain in the Merkle tree
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MembershipProof {
    // ... fields ...
}

impl MembershipProof {
    /// Verifies the membership proof
    ///
    /// # Returns
    /// - `Ok(())` if the proof is valid
    /// - `Err(_)` if the proof is invalid or an error occurred during verification
    pub fn verify(&self) -> Result<()> {
        // ... implementation ...
    }
}

289-297: LGTM! Consider enhancing documentation

The HashchainResponse enum is well-designed and provides a clear way to represent the result of fetching tree values. The variants and their associated data are appropriate for the use case.

To further improve the documentation, consider adding a brief description of the enum itself, not just its variants. For example:

/// Represents the response when fetching tree values, encapsulating both successful retrievals and proofs of non-existence
#[derive(Debug)]
pub enum HashchainResponse {
    // ... existing variants and comments ...
}

382-394: Improve error handling and consider optimization

The updated process_operation method correctly uses pattern matching with the new HashchainResponse enum. However, there are a couple of points that could be improved:

  1. The error message in the NotFound case could be more descriptive.
  2. The clone() of operation on line 384 might be unnecessary if perform_operation can accept a reference.

Consider applying these changes:

 match self.get(key_hash)? {
     Found(mut current_chain, _) => {
-        let new_entry = current_chain.perform_operation(operation.clone())?;
+        let new_entry = current_chain.perform_operation(operation)?;
         debug!("updating hashchain for user id {}", id.clone());
         let proof = self.update(key_hash, new_entry.clone())?;
         Ok(Proof::Update(proof))
     }
     NotFound(_) => {
-        bail!("Failed to get hashchain for ID {}", id)
+        bail!("Hashchain not found for ID {}. Cannot perform operation.", id)
     }
 }

Also, ensure that the perform_operation method of Hashchain accepts a reference to Operation if possible, to avoid unnecessary cloning.


553-572: LGTM! Consider minor optimization

The updated get method implementation looks good. It correctly handles both cases when retrieving the value and properly constructs the MembershipProof and NonMembershipProof objects. The method now returns the appropriate variants of HashchainResponse.

Consider a minor optimization to avoid cloning the deserialized value:

 match value {
     Some(serialized_value) => {
         let deserialized_value = Self::deserialize_value(&serialized_value)?;
         let membership_proof = MembershipProof {
             root,
             proof,
             key,
-            value: deserialized_value.clone(),
+            value: deserialized_value,
         };
-        Ok(Found(deserialized_value, membership_proof))
+        Ok(Found(membership_proof.value, membership_proof))
     }
     None => {
         let non_membership_proof = NonMembershipProof { root, proof, key };
         Ok(NotFound(non_membership_proof))
     }
 }

This change avoids an unnecessary clone of the deserialized value.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c908596 and ae4cce0.

📒 Files selected for processing (3)
  • crates/common/src/test_utils.rs (2 hunks)
  • crates/common/src/tree.rs (13 hunks)
  • crates/prism/src/node_types/sequencer.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/common/src/test_utils.rs
🧰 Additional context used
🔇 Additional comments (3)
crates/prism/src/node_types/sequencer.rs (2)

1-1: LGTM: Import changes enhance error handling and response management.

The addition of bail and the updated imports from prism_common::tree align with the changes in error handling and hashchain response management throughout the file.

Also applies to: 5-7


Line range hint 1-599: Overall: Solid improvements to error handling and response management.

The changes in this file effectively introduce the HashchainResponse type and improve error handling throughout the Sequencer implementation. The use of bail! and pattern matching enhances the code's robustness and readability. The modifications are well-aligned with Rust best practices and the codebase's evolving architecture.

crates/common/src/tree.rs (1)

303-303: LGTM! Improved method signature

The updated get method signature in the SnarkableTree trait is a good improvement. Returning Result<HashchainResponse> simplifies the API and aligns well with the new HashchainResponse enum. This change makes the code more readable and easier to use, while also providing a clear way to handle both successful retrievals and proofs of non-existence.

crates/common/src/tree.rs Show resolved Hide resolved
Copy link
Contributor

@distractedm1nd distractedm1nd left a comment

Choose a reason for hiding this comment

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

utACK, lets see what CI says

@jns-ps jns-ps self-assigned this Oct 9, 2024
Copy link
Contributor

@sebasti810 sebasti810 left a comment

Choose a reason for hiding this comment

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

beautiful

@jns-ps jns-ps merged commit 1f81adb into main Oct 9, 2024
6 checks passed
@jns-ps jns-ps deleted the include-proof-in-ws-response branch October 9, 2024 08:33
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