Skip to content

fix: implement hash32_to_scalar function for modular reduction of big-endian hashes - #4

Open
PastaPastaPasta wants to merge 1 commit into
mainfrom
refac-hash-to-scalar
Open

fix: implement hash32_to_scalar function for modular reduction of big-endian hashes#4
PastaPastaPasta wants to merge 1 commit into
mainfrom
refac-hash-to-scalar

Conversation

@PastaPastaPasta

@PastaPastaPasta PastaPastaPasta commented Aug 12, 2025

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Refactor

    • Centralized the conversion of hashed values to scalars in secure aggregation, replacing duplicated logic for more consistent handling and easier maintenance. Behavior and results remain unchanged.
  • Chores

    • Internal cleanup to reduce redundancy in hashing workflows.
  • No Public API Changes

    • External behavior, inputs, and outputs remain the same; no action required from users.

@coderabbitai

coderabbitai Bot commented Aug 12, 2025

Copy link
Copy Markdown

Walkthrough

Refactors secure_aggregation by introducing a private helper (hash32_to_scalar) to convert 32-byte hashes into scalars. Replaces duplicated inline conversion logic in two functions with this helper. Hashing workflow, error behavior, and public API remain unchanged.

Changes

Cohort / File(s) Summary
Internal refactor: hash-to-scalar helper
src/secure_aggregation.rs
Added private helper hash32_to_scalar for 32-byte hash-to-scalar conversion; updated hash_public_keys_with_sorted and hash_public_keys_with_sorted_mode to use it; centralized endianness handling; preserved existing hashing flow and errors; no public API changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Possibly related PRs

Poem

I nibble on bytes, flip endians with care,
One helper to rule them—no copies to spare.
Keys in a row, the hashes align,
Scalars emerge, all tidy and fine.
Thump goes my paw: refactor divine! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refac-hash-to-scalar

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.

❤️ 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/secure_aggregation.rs (1)

41-43: Consider using fill() for better clarity.

The loop that zeros out prefix bytes could be more concise using the fill() method.

-    // Zero out any prefix bytes
-    for byte in &mut repr_bytes[..offset] {
-        *byte = 0;
-    }
+    // Zero out any prefix bytes
+    repr_bytes[..offset].fill(0);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be108b2 and 7a8f626.

📒 Files selected for processing (1)
  • src/secure_aggregation.rs (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/secure_aggregation.rs (6)
examples/verify_secure_example.rs (1)
  • PublicKey (35-35)
src/aggregate_signature.rs (1)
  • default (55-57)
src/signature.rs (1)
  • default (47-49)
src/signature_share.rs (1)
  • default (15-17)
src/impls.rs (1)
  • default (31-33)
tests/utils.rs (1)
  • default (38-40)
🔇 Additional comments (3)
src/secure_aggregation.rs (3)

9-52: LGTM! Well-designed helper function for hash-to-scalar conversion.

The implementation correctly handles the conversion from a 32-byte big-endian hash to a scalar field element with proper modular reduction. The function appropriately:

  • Validates the representation size
  • Handles endianness conversion (big-endian to little-endian)
  • Performs automatic modular reduction via from_repr
  • Returns clear error messages

This refactoring successfully eliminates code duplication and centralizes the hash-to-scalar conversion logic.


106-108: LGTM! Clean refactoring to use the new helper function.

The replacement of the inline conversion logic with hash32_to_scalar maintains the same functionality while improving code maintainability.


312-314: LGTM! Consistent refactoring in legacy mode function.

The replacement in hash_public_keys_with_sorted_mode mirrors the change in the standard version, maintaining consistency across the codebase.

Comment thread src/secure_aggregation.rs
Comment on lines +29 to +34
// Ensure we have enough space for the hash
if repr_bytes.len() < 32 {
return Err(BlsError::InvalidInputs(
"Field representation too small for 32-byte hash".to_string(),
));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider caching the representation size check.

Since the field representation size is a compile-time constant for a given curve implementation, this check will always pass or fail consistently. Consider making this a debug assertion or documenting why 32 bytes is always safe for the supported curves.

Let me verify the field element sizes for the supported curve implementations:


🏁 Script executed:

#!/bin/bash
# Check the field element representation sizes for supported curves
# Look for curve implementations and their field sizes

# Find all BLS curve implementations
echo "=== Finding BLS curve implementations ==="
fd -e rs | xargs rg -l "impl.*BlsSignatureImpl|impl.*Pairing" | head -20

# Check for field element sizes or scalar representations
echo -e "\n=== Checking field/scalar sizes ==="
rg -A 5 "Scalar.*Repr|PrimeField.*Repr|MODULUS|field.*256|field.*381" --type rust

# Look for any documentation about field sizes
echo -e "\n=== Checking for field size documentation ==="
rg -i "field.*size|scalar.*size|32.*byte|256.*bit|381.*bit" --type rust | head -20

Length of output: 3643


Use a compile‐time or debug assertion for the 32-byte hash bound

Instead of a one‐off runtime check, leverage the fact that <PrimeField>::Repr has a fixed size (e.g. 48 bytes for BLS12-381) and enforce the requirement at compile or debug time:

  • In src/secure_aggregation.rs (around lines 29–34), replace:
    // Ensure we have enough space for the hash
    if repr_bytes.len() < 32 {
        return Err(BlsError::InvalidInputs(
            "Field representation too small for 32-byte hash".to_string(),
        ));
    }
    with a debug assertion:
    debug_assert!(
        repr_bytes.len() >= 32,
        "Field representation ({}) too small for 32-byte hash",
        repr_bytes.len()
    );
  • Or, pull the length into a constant and use a compile-time assertion (via static_assertions or a const_assert! macro):
    const REPR_BYTES: usize = std::mem::size_of::<<<C as Pairing>::PublicKey as Group>::Scalar
        as PrimeField>::Repr>();
    const_assert!(REPR_BYTES >= 32, "Repr must be at least 32 bytes");
  • Add a short doc comment (or README entry) stating that all supported curves (currently BLS12-381, etc.) have ≥ 32 bytes of field repr, so this bound is always satisfied.

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