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

refactor: Increase code reuse in hashchain and tree #146

Merged
merged 13 commits into from
Nov 1, 2024

Conversation

jns-ps
Copy link
Contributor

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

Summary by CodeRabbit

  • New Features

    • Enhanced validation logic for the last entry in the hashchain, improving security and reliability.
    • Updated service registration and account creation processes to utilize a consistent instantiation method.
  • Bug Fixes

    • Streamlined the handling of empty entries to prevent errors during validation processes.
    • Improved error handling with more context during hashchain operations.
  • Refactor

    • Improved readability and maintainability of key methods within the Hashchain structure by simplifying logic and flow.
    • Refined control flow in the KeyDirectoryTree for better clarity in operation processing.
    • Updated method names and signatures for clarity and consistency in the handling of hashchain operations.

Copy link
Contributor

coderabbitai bot commented Oct 17, 2024

Walkthrough

The changes involve substantial modifications to the Hashchain struct and its methods in the crates/common/src/hashchain.rs file. The create_account and register_service methods have been removed, while the verify_last_entry method has been refactored for improved logic and error handling. The is_key_revoked method has been renamed to is_key_invalid, with updated logic for checking key validity. Additionally, the validate_new_operation method has been enhanced to provide more detailed error messages. Related updates were made in the TestTreeState struct and the KeyDirectoryTree implementation in other files.

Changes

File Path Change Summary
crates/common/src/hashchain.rs Refactored verify_last_entry; removed create_account and register_service; renamed is_key_revoked to is_key_invalid; updated validate_new_operation.
crates/common/src/test_utils.rs Updated register_service to create Hashchain with from_operation; modified create_random_insert and create_random_update for consistency in operation handling.
crates/common/src/tree.rs Changed insert and update methods to accept insertion_op and update_op instead of direct values; improved error handling in these methods.

Possibly related PRs

Suggested reviewers

  • distractedm1nd
  • sebasti810

Poem

In the land of code, where rabbits play,
A hashchain hops, in a clever way.
With entries checked from last to first,
The logic flows, no longer cursed.
Revoked keys now find their place,
In this code, we embrace the grace! 🐇✨


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.

@jns-ps jns-ps self-assigned this Oct 17, 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: 4

🧹 Outside diff range and nitpick comments (1)
crates/common/src/hashchain.rs (1)

221-221: Replace println! with a proper logging mechanism.

Using println! for logging is not ideal in production code. Consider using a logging crate like log or tracing for better control over log levels and output destinations.

Apply this diff to replace println! with log::debug!:

- println!("Validating op {}", operation);
+ log::debug!("Validating operation: {:?}", operation);

Make sure to include the logging crate in your dependencies and initialize the logger appropriately.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4a03e7b and 4c412af.

📒 Files selected for processing (1)
  • crates/common/src/hashchain.rs (3 hunks)
🧰 Additional context used
🔇 Additional comments (1)
crates/common/src/hashchain.rs (1)

232-232: Ensure correct index usage in get_key_at_index.

When retrieving the signing key with get_key_at_index(args.signature.key_idx as usize), confirm that key_idx correctly corresponds to the desired entry. Off-by-one errors here could lead to signature verification failures or incorrect behavior.

It's important to verify that args.signature.key_idx accurately reflects the position of the key in the hashchain. Consider adding checks or unit tests to validate this behavior.

crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/hashchain.rs 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 (1)
crates/common/src/hashchain.rs (1)

Line range hint 220-244: Refinements needed in validate_operation_at_idx

The new validate_operation_at_idx method is a good addition, but there are a few points to address:

  1. Remove or replace the debug print statement:

    - println!("Validating op {}", operation);
    + log::debug!("Validating operation: {}", operation);
  2. The CreateAccount operation check has been correctly updated to reference "CreateAccount" instead of "RegisterService". This resolves the issue mentioned in a previous review comment.

  3. Consider adding a check for the RegisterService operation to ensure it's only allowed as the first entry in an empty hashchain:

    Operation::RegisterService(_) => {
    -   if idx > 0 {
    +   if !self.entries.is_empty() {
            bail!("RegisterService operation must be the first entry");
        }
        Ok(())
    }

These changes will improve the robustness and maintainability of the validation process.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4c412af and 5af5344.

📒 Files selected for processing (1)
  • crates/common/src/hashchain.rs (3 hunks)
🧰 Additional context used
🔇 Additional comments (2)
crates/common/src/hashchain.rs (2)

108-125: Excellent refactoring of verify_last_entry method

The refactoring of the verify_last_entry method is a significant improvement:

  1. It uses a reverse iterator, which is more efficient for this use case.
  2. It handles edge cases (empty chain, single entry) explicitly.
  3. The logic for verifying the last entry against the second-to-last entry is clear and correct.

This refactoring enhances both the robustness and readability of the code.


211-218: Improved robustness in validate_new_operation

The changes to validate_new_operation are well-considered:

  1. The check for empty entries adds robustness to the validation process.
  2. The use of validate_operation_at_idx improves code reusability and maintainability.

These changes enhance the overall reliability of the operation validation process.

crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps force-pushed the hashchain-code-reuse branch from 5af5344 to 10e4b30 Compare October 17, 2024 13:49
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 (1)
crates/common/src/hashchain.rs (1)

108-125: Improved implementation of verify_last_entry

The refactoring of verify_last_entry is a significant improvement. It now handles different cases (empty, single entry, and multiple entries) more explicitly and efficiently. The use of a reverse iterator simplifies the logic.

Consider extracting the validation logic for 2+ entries into a separate private method for improved readability:

fn validate_multiple_entries(&self, last_entry: &HashchainEntry, second_last_entry: &HashchainEntry, second_last_idx: usize) -> Result<()> {
    if last_entry.previous_hash != second_last_entry.hash {
        bail!("Previous hash mismatch for the last entry");
    }
    self.validate_operation_at_idx(&last_entry.operation, second_last_idx)
}

Then, you can call this method in the main function:

if let Some((second_last_idx, second_last_entry)) = rev_iter.next() {
    self.validate_multiple_entries(last_entry, second_last_entry, second_last_idx)
} else {
    // When there is only 1 item in the chain, validate insertion at idx 0
    self.validate_operation_at_idx(&last_entry.operation, last_idx)
}

This separation of concerns could make the main function even more readable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5af5344 and 67f3b18.

📒 Files selected for processing (1)
  • crates/common/src/hashchain.rs (3 hunks)
🧰 Additional context used
🔇 Additional comments (1)
crates/common/src/hashchain.rs (1)

168-178: ⚠️ Potential issue

Optimize is_key_revoked_before_idx method

The new method provides a good abstraction for checking key revocation status, but there are two areas for improvement:

  1. The use of skip(idx) is incorrect as it skips the entries we want to check.
  2. The default return value of true might not be the desired behavior.

Consider the following changes:

fn is_key_revoked_before_idx(&self, key: VerifyingKey, idx: usize) -> bool {
    self.iter()
-       .skip(idx)
+       .take(idx + 1)
        .rev()
        .find_map(|entry| match entry.operation.clone() {
            Operation::RevokeKey(args) if args.value == key => Some(true),
            Operation::AddKey(args) if args.value == key => Some(false),
            Operation::CreateAccount(args) if args.value == key => Some(false),
            _ => None,
        })
-       .unwrap_or(true)
+       .unwrap_or(false)
}

These changes ensure that:

  1. All relevant entries up to idx are checked.
  2. A key is considered not revoked unless explicitly revoked by an operation.

crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps force-pushed the hashchain-code-reuse branch 2 times, most recently from 0440bd6 to aeebc35 Compare October 30, 2024 09:24
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 (3)
crates/common/src/test_utils.rs (1)

Line range hint 266-269: Remove unnecessary clone of operation.

The operation is only used once in Hashchain::from_operation, so cloning it is unnecessary.

pub fn create_new_hashchain(id: &str, signing_key: &SigningKey, service: Service) -> Hashchain {
    let op = Operation::new_create_account(id.to_string(), signing_key, service.id, &service.sk)
        .unwrap();
-    Hashchain::from_operation(op.clone()).unwrap()
+    Hashchain::from_operation(op).unwrap()
}
crates/common/src/hashchain.rs (1)

207-211: Improve error message for RegisterService validation

The error message could be more informative by including the actual index where the operation was attempted.

Apply this change:

            Operation::RegisterService(_) => {
                if idx > 0 {
-                   bail!("RegisterService operation must be the first entry");
+                   bail!("RegisterService operation must be the first entry, but was attempted at index {}", idx);
                }
                Ok(())
            }
crates/common/src/tree.rs (1)

Line range hint 477-481: Improve error message clarity for duplicate service registration.

The current error message "empty slot for ID" is confusing when indicating that a service already exists. Additionally, using DatabaseError::NotFoundError is semantically incorrect for this case.

-bail!(DatabaseError::NotFoundError(format!(
-    "empty slot for ID {}",
-    id
-)));
+bail!("Service with ID {} already exists", id);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 67f3b18 and aeebc35.

📒 Files selected for processing (3)
  • crates/common/src/hashchain.rs (5 hunks)
  • crates/common/src/test_utils.rs (1 hunks)
  • crates/common/src/tree.rs (3 hunks)
🔇 Additional comments (3)
crates/common/src/test_utils.rs (1)

53-56: LGTM! Consistent with operation validation refactoring.

The change standardizes Hashchain creation by using from_operation with a register service operation, which aligns well with the PR's objective of reusing operation validation code.

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

219-224: 🛠️ Refactor suggestion

Optimize validation order in key operations

The key lookup is performed before checking if the key is revoked, which could be inefficient. Consider checking revocation status first to avoid unnecessary key lookups.

Apply this optimization:

            Operation::AddKey(KeyOperationArgs { signature, .. })
            | Operation::RevokeKey(KeyOperationArgs { signature, .. })
            | Operation::AddData(AddDataArgs {
                op_signature: signature,
                ..
            }) => {
+               let signing_key = self.get_key_at_index(signature.key_idx)?;
+               if self.is_key_revoked_before_idx(signing_key.clone(), idx) {
+                   bail!("The signing key is revoked");
+               }
-               let signing_key = self.get_key_at_index(signature.key_idx)?;
-               if self.is_key_revoked_before_idx(signing_key.clone(), idx) {
-                   bail!("The signing key is revoked");
-               }
                operation.verify_user_signature(signing_key.clone())
            }

Likely invalid or redundant comment.

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

Line range hint 590-824: Well-structured and comprehensive test coverage.

The test suite effectively covers:

  • Happy path scenarios
  • Error cases
  • Edge cases
  • Batch operations
  • State transitions

crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps force-pushed the hashchain-code-reuse branch from aeebc35 to 77ac055 Compare October 31, 2024 10:37
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 (1)
crates/common/src/hashchain.rs (1)

192-192: Consider enhancing CreateAccount error message for consistency.

Other operations provide detailed error messages with context, but the CreateAccount operation uses a simple message. Consider making it consistent with other operations:

- bail!("CreateAccount operation must be the first entry");
+ bail!(
+     "CreateAccount operation must be the first entry, but found {} existing entries",
+     self.entries.len()
+ );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between aeebc35 and 77ac055.

📒 Files selected for processing (3)
  • crates/common/src/hashchain.rs (3 hunks)
  • crates/common/src/test_utils.rs (5 hunks)
  • crates/common/src/tree.rs (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/common/src/test_utils.rs
  • crates/common/src/tree.rs
🔇 Additional comments (2)
crates/common/src/hashchain.rs (2)

108-108: Default behavior in key revocation needs adjustment.

This issue was previously identified. The default return value of true could incorrectly mark keys as revoked when they haven't been explicitly revoked.


146-149: LGTM! Improved error messages with detailed context.

The enhanced error messages now provide better context by including the actual and expected hash values, making debugging easier.

Also applies to: 155-161, 173-179

crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps changed the title refac(hashchain): Reuse operation validation code refactor: Increase code reuse in hashchain and tree Oct 31, 2024
crates/common/src/hashchain.rs Show resolved Hide resolved
crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/hashchain.rs Outdated Show resolved Hide resolved
crates/common/src/tree.rs Show resolved Hide resolved
crates/common/src/tree.rs Show resolved Hide resolved
crates/common/src/tree.rs Outdated Show resolved Hide resolved
@jns-ps jns-ps force-pushed the hashchain-code-reuse branch from 77ac055 to 5c55fef Compare October 31, 2024 13:57
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: 4

🧹 Outside diff range and nitpick comments (2)
crates/common/src/hashchain.rs (1)

Line range hint 99-108: Consider adjusting the default behavior in is_key_invalid.

The method currently defaults to considering keys as invalid (returns true) when no matching operation is found. This might be too restrictive, especially for new keys or empty chains.

Consider changing the default to false to assume keys are valid unless explicitly invalidated:

            })
-           .unwrap_or(true)
+           .unwrap_or(false)
crates/common/src/test_utils.rs (1)

194-207: Improve error handling in random insert creation.

While the operation-centric approach is good, there are a few improvements that could be made:

  1. The expect message on line 200 is phrased as a success message but is used for error handling.
  2. The error handling could be more descriptive by including the actual error.

Consider this improvement:

-        .expect("Creating account operation should succeed");
+        .expect("Failed to create account operation");

Also consider adding the error details:

-            let proof = state.tree.insert(key_hash, operation).expect("Insert should succeed");
+            let proof = state.tree.insert(key_hash, operation)
+                .expect("Failed to insert into tree: key_hash={key_hash}");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 77ac055 and 5c55fef.

📒 Files selected for processing (3)
  • crates/common/src/hashchain.rs (4 hunks)
  • crates/common/src/test_utils.rs (5 hunks)
  • crates/common/src/tree.rs (10 hunks)
🔇 Additional comments (4)
crates/common/src/test_utils.rs (1)

55-58: LGTM: Service registration refactor looks good.

The change to use Operation::new_register_service and Hashchain::from_operation aligns well with the operation-centric design pattern.

Let's verify the consistency of this pattern across the codebase:

✅ Verification successful

Let me gather more context about the usage patterns to ensure completeness of the verification.


Service registration refactor is correctly implemented

The verification confirms that:

  • The new operation-centric approach using Operation::new_register_service is consistently used across the codebase
  • All register_service occurrences in test files are using the new pattern through test utilities
  • The RegisterService operation is properly integrated into the operation handling system with appropriate validation logic

The changes align with the operation-centric design pattern and maintain consistency throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining direct service registration calls
# that might have been missed in the refactor

# Search for direct service registration patterns
rg -l "register_service|RegisterService" --type rust

# Search for the new operation-based pattern
ast-grep --pattern 'Operation::new_register_service'

Length of output: 723


Script:

#!/bin/bash
# Check the implementation and usage context of register_service
rg "register_service" -B 2 -A 2 --type rust

# Check RegisterService struct/enum definition and usage
rg "RegisterService" -B 2 -A 2 --type rust

Length of output: 15222

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

75-75: LGTM! Improved type safety in proof structures.

The change from raw values to domain-specific types (Operation) enhances type safety and makes the code more maintainable.

Also applies to: 101-102


237-238: LGTM! Debug logging restored.

The debug logging has been readded as requested in the previous review.


Line range hint 333-362: LGTM! Improved error handling and type safety.

The update implementation now properly handles errors and validates operations before applying them.

crates/common/src/hashchain.rs Show resolved Hide resolved
crates/common/src/test_utils.rs Show resolved Hide resolved
crates/common/src/tree.rs Show resolved Hide resolved
crates/common/src/tree.rs Show resolved Hide resolved
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.

2 participants