Skip to content

test: add signature_sets unit tests and fix createSingleSignatureSetFromComponents#313

Open
gorusys wants to merge 3 commits intoChainSafe:mainfrom
gorusys:test/signature_sets
Open

test: add signature_sets unit tests and fix createSingleSignatureSetFromComponents#313
gorusys wants to merge 3 commits intoChainSafe:mainfrom
gorusys:test/signature_sets

Conversation

@gorusys
Copy link
Copy Markdown
Contributor

@gorusys gorusys commented Apr 13, 2026

No description provided.

@gorusys gorusys requested a review from a team as a code owner April 13, 2026 18:05
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a minor bug in the createSingleSignatureSetFromComponents function by ensuring the public key is correctly assigned. More significantly, it introduces a robust suite of unit tests for both single and aggregated signature set verification, enhancing the reliability and correctness of BLS signature handling within the state transition utilities.

Highlights

  • Bug Fix: Corrected the createSingleSignatureSetFromComponents function to properly dereference the public key pointer, ensuring correct assignment of the public key to the SingleSignatureSet struct.
  • Unit Tests for SingleSignatureSet: Added comprehensive unit tests for verifySingleSignatureSet, covering scenarios such as valid sets, mismatched signing roots, incorrect public key signers, and invalid signature byte encodings.
  • Unit Tests for AggregatedSignatureSet: Introduced unit tests for verifyAggregatedSignatureSet, including checks for valid single-key aggregates, mismatched signing roots, and cases where public keys do not correspond to the signers.
  • Function Validation Test: Included a test to verify that createSingleSignatureSetFromComponents produces a SingleSignatureSet equivalent to one created directly via a struct literal, confirming the function's correct behavior after the fix.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive suite of unit tests for signature set verification and updates the createSingleSignatureSetFromComponents function. Feedback focuses on adhering to the repository style guide, specifically regarding the use of assertions, out-pointers for large structs, and passing large arguments by constant pointer. Additionally, several lines in the new tests exceed the 100-column limit, and an improvement was suggested for a test case to ensure it validates individual struct fields rather than just the final verification result.

pub fn createSingleSignatureSetFromComponents(pubkey: *const PublicKey, signing_root: Root, signature: BLSSignature) SingleSignatureSet {
return .{
.pubkey = pubkey,
.pubkey = pubkey.*,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The function createSingleSignatureSetFromComponents violates several rules from the Repository Style Guide:

  1. Assertions: All function arguments must be asserted (Line 51). This function currently has no assertions. Even for simple constructors, the guide requires an average of two assertions per function to ensure data integrity.
  2. Out-pointers: For structs larger than 16 bytes (this struct is ~224 bytes), the guide recommends initialization in-place using an out-pointer to avoid intermediate copy-move allocations and stack growth (Line 318).
  3. Pass-by-pointer: Arguments larger than 16 bytes (like Root at 32 bytes and BLSSignature at 96 bytes) should be passed as *const to avoid unnecessary copies (Line 314).

While the function signature is not part of this diff, consider refactoring it to adhere to these safety and performance standards.

References
  1. Assert all function arguments and return values, pre/postconditions and invariants. (link)
  2. Construct larger structs in-place by passing an out pointer during initialization. (link)
  3. If the argument type is more than 16 bytes, then pass the argument as *const. (link)

const signature = sign(secret_key, &signing_root);
const public_key = secret_key.toPublicKey();
var pubkeys = [_]PublicKey{public_key};
const set = createAggregateSignatureSetFromComponents(pubkeys[0..], signing_root, signature.compress());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This line exceeds the 100-column limit (it is 108 columns), violating the Repository Style Guide (Line 400). Please wrap the function call.

    const set = createAggregateSignatureSetFromComponents(
        pubkeys[0..],
        signing_root,
        signature.compress(),
    );
References
  1. Hard limit all line lengths, without exception, to at most 100 columns. (link)

const public_key = secret_key.toPublicKey();
signing_root[31] ^= 0xff;
var pubkeys = [_]PublicKey{public_key};
const set = createAggregateSignatureSetFromComponents(pubkeys[0..], signing_root, signature.compress());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This line exceeds the 100-column limit (108 columns), violating the Repository Style Guide (Line 400).

    const set = createAggregateSignatureSetFromComponents(
        pubkeys[0..],
        signing_root,
        signature.compress(),
    );
References
  1. Hard limit all line lengths, without exception, to at most 100 columns. (link)

const signing_root = [_]u8{1} ** 32;
const signature = sign(secret_key_a, &signing_root);
var pubkeys = [_]PublicKey{secret_key_b.toPublicKey()};
const set = createAggregateSignatureSetFromComponents(pubkeys[0..], signing_root, signature.compress());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This line exceeds the 100-column limit (108 columns), violating the Repository Style Guide (Line 400).

    const set = createAggregateSignatureSetFromComponents(
        pubkeys[0..],
        signing_root,
        signature.compress(),
    );
References
  1. Hard limit all line lengths, without exception, to at most 100 columns. (link)

Comment on lines +170 to +171
try std.testing.expect(try verifySingleSignatureSet(&from_fn));
try std.testing.expect(try verifySingleSignatureSet(&literal));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The test 'createSingleSignatureSetFromComponents matches equivalent struct literal' should explicitly verify that the fields of the created struct match the expected values. Simply verifying the signature is a weak check for a factory function.

    try std.testing.expect(from_fn.pubkey.isEqual(&literal.pubkey));
    try std.testing.expectEqual(literal.signing_root, from_fn.signing_root);
    try std.testing.expectEqual(literal.signature, from_fn.signature);
    try std.testing.expect(try verifySingleSignatureSet(&from_fn));

try std.testing.expect(try verifySingleSignatureSet(&set));
}

test "verifySingleSignatureSet returns false when signing root does not match signed message" {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we make this group of similar tests using table driven approach to reduce verbose test code?

.signing_root = signing_root,
.signature = signature.compress(),
};
try std.testing.expect(!try verifySingleSignatureSet(&set));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit:use expectEqual false for negative check

@gorusys gorusys requested a review from GrapeBaBa April 17, 2026 10:51
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