Skip to content

pkc%feat(bls): migrate operational types to Bls{PublicKey,SecretKey,BlsSignature}<S>, reap bls_{chia,ietf} modules for unified bls module - #25

Merged
kwvg merged 14 commits into
dashpay:developfrom
kwvg:pkc_p2
Aug 10, 2026
Merged

kwvg merged 14 commits into
dashpay:developfrom
kwvg:pkc_p2

Conversation

@kwvg

@kwvg kwvg commented Aug 10, 2026 •

Copy link
Copy Markdown
Collaborator

Additional Information

Breaking Changes

Old New
SecretKey::to_bytes() -> [u8; 32] BlsSecretKey::<S>::to_bytes() -> Zeroizing<[u8; 32]>
bls_chia::{PublicKey, SecretKey, Signature} bls::{BlsPublicKey, BlsSecretKey, BlsSignature}<BlsScChia>
bls_ietf::{PublicKey, SecretKey, Signature} bls::{BlsPublicKey, BlsSecretKey, BlsSignature}<BlsScIetf>
bls_{chia,ietf}::threshold::SecretKeyShare bls::BlsSkShare<S>
bls_{chia,ietf}::threshold::SignatureShare bls::BlsSigShare<S>
bls_ietf::Scheme bls::BlsSigId
PublicKey::dh_exchange(sk, peer_pk) BlsSecretKey::<S>::dh_exchange(&self, peer_pk)
bls_ietf::SecretKey::prove_possession, bls_ietf::PublicKey::verify_possession bls::BlsSecretKey::<BlsScIetf>::prove_possession, bls::BlsPublicKey::<BlsScIetf>::verify_possession
bls_{chia,ietf}::aggregate_pk BlsPublicKey::<S>::aggregate
bls_{chia,ietf}::aggregate_sk BlsSecretKey::<S>::aggregate
bls_{chia,ietf}::aggregate_sig BlsSignature::<S>::aggregate
bls_{chia,ietf}::{fast,secure}_verify_aggregates methods of the same name on BlsSignature<S>
bls_ietf::verify_aggregates BlsSignature::<BlsScIetf>::verify_aggregates
bls_{chia,ietf}::threshold::split_sk(sk, threshold, ids, rng) BlsSecretKey::<S>::split(&self, threshold, ids, rng)
bls_{chia,ietf}::threshold::recover_sig(shares) BlsSignature::<S>::recover(shares)
bls_{chia,ietf}::threshold::derive_pk_share(master_pks, id) BlsPublicKey::<S>::derive_share(master_pks, id)

How Has This Been Tested?

cargo fmt --check
cargo test --features full
cargo clippy --features full --all-targets
./contrib/lint_all.py --exclude lint_codeql
./contrib/lint/lint_codeql.py --with-suite rust-security-and-quality

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional tests
  • I have made corresponding changes to the documentation (note: N/A)
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 0.1 milestone Aug 10, 2026
@kwvg kwvg self-assigned this Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Note

This pull request has no conflicts! 🎊 🎉 🎊

@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces separate Chia and IETF BLS APIs with scheme-generic key, signature, aggregation, threshold, and proof-of-possession APIs. It removes legacy modules, updates benchmarks and dependencies, and adjusts CodeQL secret classification.

Changes

Generic BLS API

Layer / File(s) Summary
BLS module and scheme foundation
pkgs/pkc/Cargo.toml, pkgs/pkc/src/bls/*, pkgs/pkc/src/prelude.rs
The crate wires generic BLS modules, exposes FFI wrappers, strengthens scheme bounds, updates test configuration, and replaces hex-literal. Legacy Chia and IETF modules and shared contracts are removed.
Generic keys, signatures, and proof of possession
pkgs/pkc/src/bls/public_ops.rs, pkgs/pkc/src/bls/secret_ops.rs, pkgs/pkc/src/bls/sig_basic.rs, pkgs/pkc/src/bls/sig_pop.rs
The new wrappers provide key generation, serialization, signing, verification, DH exchange, conversions, hashing, zeroization, IETF domain separation, and proof-of-possession operations.
Aggregation and threshold operations
pkgs/pkc/src/bls/share_ops.rs, pkgs/pkc/src/bls/sig_aggregate.rs, pkgs/pkc/src/bls/sig_threshold.rs
The generic API adds public-key and signature aggregation, aggregate verification, threshold splitting, share derivation, signature recovery, and validation tests.
Unified BLS benchmarks
pkgs/pkc/bench/bls.rs, pkgs/pkc/bench/main.rs
The benchmark harness uses one BLS module and measures signing, verification, aggregation, serialization, threshold operations, IETF operations, and parallel standard-library operations.

CodeQL secret classification

Layer / File(s) Summary
Secret-type classification
contrib/codeql/lib/policy.qll, contrib/codeql/zeroize.ql
CodeQL excludes BlsSigShare and classifies types that satisfy wipesSelf as secret-bearing.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant BlsSecretKey
  participant BlsSignature
  participant BlsScheme
  Caller->>BlsSecretKey: sign(message)
  BlsSecretKey->>BlsScheme: sign_with(secret key, message)
  BlsScheme-->>BlsSecretKey: inner signature
  BlsSecretKey-->>Caller: BlsSignature
  Caller->>BlsSignature: verify(message, public key)
  BlsSignature->>BlsScheme: verify_with(signature, message, public key)
  BlsScheme-->>BlsSignature: verify_ok(BLST_ERROR)
  BlsSignature-->>Caller: Result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the migration to generic BLS types and the removal of separate scheme modules.
Description check ✅ Passed The description directly explains the BLS migration, breaking API changes, security updates, dependencies, and testing performed.

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

@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: 3

🧹 Nitpick comments (3)
pkgs/pkc/src/bls/scheme_ietf.rs (1)

158-179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the DST selection into one helper.

sign_with and verify_with repeat the same match over BlsSigId. If one copy changes, signing and verification can select different domain separation tags, and the mismatch is silent until a verification fails.

♻️ Proposed refactor
 impl BlsScIetf {
+  /// Select the DST for the given signature scheme id.
+  fn dst_for(id: BlsSigId) -> &'static [u8] {
+    match id {
+      BlsSigId::Basic => DST_BASIC,
+      BlsSigId::ProofOfPossession => DST_POP,
+    }
+  }
+
   /// Sign under the DST selected by `id`.
   pub(crate) fn sign_with(sk: &SecretKey, msg: &[u8], id: BlsSigId) -> Signature {
-    let dst = match id {
-      BlsSigId::Basic => DST_BASIC,
-      BlsSigId::ProofOfPossession => DST_POP,
-    };
-    sk.sign(msg, dst, &[])
+    sk.sign(msg, Self::dst_for(id), &[])
   }
 
   /// Verify under the DST selected by `id`.
   ///
   /// # Errors
   ///
   /// Returns `VerifyFailed` when the pairing check does not hold.
   pub(crate) fn verify_with(sig: &Signature, msg: &[u8], pk: &PublicKey, id: BlsSigId) -> Result<(), BlsError> {
-    let dst = match id {
-      BlsSigId::Basic => DST_BASIC,
-      BlsSigId::ProofOfPossession => DST_POP,
-    };
-    verify_ok(sig.verify(true, msg, dst, &[], pk, true))
+    verify_ok(sig.verify(true, msg, Self::dst_for(id), &[], pk, true))
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkgs/pkc/src/bls/scheme_ietf.rs` around lines 158 - 179, Extract the shared
BlsSigId-to-DST match into a helper associated with BlsScIetf, then update
sign_with and verify_with to reuse it instead of selecting the DST
independently. Preserve the existing DST_BASIC and DST_POP mappings.
pkgs/pkc/src/bls/sig_aggregate.rs (1)

150-165: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the verify_aggregates error contract.

BlsScIetf::verify_aggregates documents CountMismatch for unequal counts and EmptyAggregation for no keys. ietf_verify_distinct_messages covers only the success path and the swapped-message path. Add cases for a message/key count mismatch and for empty inputs, so the documented error contract stays pinned.

💚 Proposed additional test
+  #[rstest]
+  fn ietf_verify_aggregates_rejects_bad_inputs() {
+    let sk = BlsSecretKey::<BlsScIetf>::generate(&SEED_0).unwrap();
+    let msg: &[u8] = b"first message";
+    let sig = sk.sign(msg);
+    let pk = sk.public_key();
+
+    assert!(matches!(
+      sig.verify_aggregates(&[msg], &[&pk, &pk]),
+      Err(BlsError::CountMismatch)
+    ));
+    assert!(matches!(
+      sig.verify_aggregates(&[], &[]),
+      Err(BlsError::EmptyAggregation)
+    ));
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkgs/pkc/src/bls/sig_aggregate.rs` around lines 150 - 165, Extend
ietf_verify_distinct_messages to assert the verify_aggregates error contract:
add a case with unequal message and public-key counts that returns
CountMismatch, and a case with empty inputs that returns EmptyAggregation. Keep
the existing successful and swapped-message assertions unchanged.
pkgs/pkc/src/bls/sig_threshold.rs (1)

17-31: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Document that Ok does not prove a sufficient quorum.

recover interpolates any set of two or more valid shares. The test assert_sub_threshold_does_not_verify at lines 79-91 confirms that a below-threshold set still returns Ok, and only verification rejects the result. The current Rustdoc does not state this. A caller can read Ok as proof of a valid quorum. Add a note that the caller must verify the recovered signature against the group public key.

📝 Proposed doc addition
   /// Recover a full signature from threshold signature shares via Lagrange
   /// interpolation in G2.
   ///
+  /// Recovery does not check that the share count reaches the threshold used
+  /// at split time. A below-threshold set still interpolates to a point and
+  /// returns `Ok`. Verify the recovered signature against the group public
+  /// key before you trust it.
+  ///
   /// # Errors
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkgs/pkc/src/bls/sig_threshold.rs` around lines 17 - 31, Update the Rustdoc
for `BlsSignature::recover` to state that successful interpolation does not
establish a sufficient quorum, since two or more valid shares may return `Ok`.
Explicitly instruct callers to verify the recovered signature against the group
public key.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkgs/pkc/bench/bls.rs`:
- Around line 171-184: Update the 1,000-item benchmark setup around BlsSecretKey
generation and test_msg calls to use inputs that remain unique across all n
entries, avoiding the u8 truncation at 256. Prefer usize-compatible helper
inputs while preserving the existing n-sized keys, messages, signatures, and
aggregate flow.

In `@pkgs/pkc/src/bls/scheme_ietf.rs`:
- Around line 203-211: Update verify_aggregates to reject duplicate entries in
msgs before invoking sig.aggregate_verify, while preserving the existing count
and empty-aggregation checks. Detect equality across the full message byte
slices, return the appropriate BlsError for invalid aggregation, and only call
aggregate_verify when all messages are unique.

In `@pkgs/pkc/src/bls/secret_ops.rs`:
- Around line 63-75: Change dh_exchange to return a dedicated shared-secret
newtype rather than BlsPublicKey, with redacted Debug, constant-time equality,
and zeroization, and update callers accordingly. Add explicit prime-order
subgroup validation in the BlsScChia DH implementation before scalar
multiplication, including validation of the peer key and resulting point as
required by the existing error contract. Add a regression test covering
rejection of an on-curve, non-subgroup peer key.

---

Nitpick comments:
In `@pkgs/pkc/src/bls/scheme_ietf.rs`:
- Around line 158-179: Extract the shared BlsSigId-to-DST match into a helper
associated with BlsScIetf, then update sign_with and verify_with to reuse it
instead of selecting the DST independently. Preserve the existing DST_BASIC and
DST_POP mappings.

In `@pkgs/pkc/src/bls/sig_aggregate.rs`:
- Around line 150-165: Extend ietf_verify_distinct_messages to assert the
verify_aggregates error contract: add a case with unequal message and public-key
counts that returns CountMismatch, and a case with empty inputs that returns
EmptyAggregation. Keep the existing successful and swapped-message assertions
unchanged.

In `@pkgs/pkc/src/bls/sig_threshold.rs`:
- Around line 17-31: Update the Rustdoc for `BlsSignature::recover` to state
that successful interpolation does not establish a sufficient quorum, since two
or more valid shares may return `Ok`. Explicitly instruct callers to verify the
recovered signature against the group public key.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dc0d1af9-30c9-4d4f-a786-35c53aa16017

📥 Commits

Reviewing files that changed from the base of the PR and between 5321155 and c5357d1.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (53)
  • contrib/codeql/lib/policy.qll
  • contrib/codeql/zeroize.ql
  • pkgs/pkc/Cargo.toml
  • pkgs/pkc/bench/bls.rs
  • pkgs/pkc/bench/bls_chia.rs
  • pkgs/pkc/bench/bls_ietf.rs
  • pkgs/pkc/bench/main.rs
  • pkgs/pkc/src/bls/blst_ffi.rs
  • pkgs/pkc/src/bls/chia_h2c.rs
  • pkgs/pkc/src/bls/mod.rs
  • pkgs/pkc/src/bls/public_ops.rs
  • pkgs/pkc/src/bls/scheme_chia.rs
  • pkgs/pkc/src/bls/scheme_ietf.rs
  • pkgs/pkc/src/bls/scheme_ops.rs
  • pkgs/pkc/src/bls/secret_ops.rs
  • pkgs/pkc/src/bls/share_ops.rs
  • pkgs/pkc/src/bls/sig_aggregate.rs
  • pkgs/pkc/src/bls/sig_basic.rs
  • pkgs/pkc/src/bls/sig_pop.rs
  • pkgs/pkc/src/bls/sig_threshold.rs
  • pkgs/pkc/src/bls/tests.rs
  • pkgs/pkc/src/bls_chia/agg.rs
  • pkgs/pkc/src/bls_chia/mod.rs
  • pkgs/pkc/src/bls_chia/pk.rs
  • pkgs/pkc/src/bls_chia/sig.rs
  • pkgs/pkc/src/bls_chia/sk.rs
  • pkgs/pkc/src/bls_chia/threshold.rs
  • pkgs/pkc/src/bls_ietf/agg.rs
  • pkgs/pkc/src/bls_ietf/mod.rs
  • pkgs/pkc/src/bls_ietf/pk.rs
  • pkgs/pkc/src/bls_ietf/sig.rs
  • pkgs/pkc/src/bls_ietf/sk.rs
  • pkgs/pkc/src/bls_ietf/threshold.rs
  • pkgs/pkc/src/common/bls/contract.rs
  • pkgs/pkc/src/common/bls/mod.rs
  • pkgs/pkc/src/common/mod.rs
  • pkgs/pkc/src/lib.rs
  • pkgs/pkc/src/prelude.rs
  • pkgs/pkc/tests/bls_chia_aggregate.rs
  • pkgs/pkc/tests/bls_chia_dh.rs
  • pkgs/pkc/tests/bls_chia_keygen.rs
  • pkgs/pkc/tests/bls_chia_llmq.rs
  • pkgs/pkc/tests/bls_chia_ser.rs
  • pkgs/pkc/tests/bls_chia_sign.rs
  • pkgs/pkc/tests/bls_chia_threshold.rs
  • pkgs/pkc/tests/bls_ietf_aggregate.rs
  • pkgs/pkc/tests/bls_ietf_dh.rs
  • pkgs/pkc/tests/bls_ietf_keygen.rs
  • pkgs/pkc/tests/bls_ietf_llmq.rs
  • pkgs/pkc/tests/bls_ietf_pop.rs
  • pkgs/pkc/tests/bls_ietf_sign.rs
  • pkgs/pkc/tests/bls_ietf_threshold.rs
  • pkgs/pkc/tests/common/mod.rs
💤 Files with no reviewable changes (33)
  • pkgs/pkc/tests/common/mod.rs
  • pkgs/pkc/src/bls_chia/sk.rs
  • pkgs/pkc/src/bls_chia/pk.rs
  • pkgs/pkc/bench/bls_ietf.rs
  • pkgs/pkc/src/bls_chia/sig.rs
  • pkgs/pkc/src/lib.rs
  • pkgs/pkc/src/bls_ietf/sig.rs
  • pkgs/pkc/tests/bls_ietf_dh.rs
  • pkgs/pkc/tests/bls_ietf_pop.rs
  • pkgs/pkc/tests/bls_ietf_keygen.rs
  • pkgs/pkc/tests/bls_chia_dh.rs
  • pkgs/pkc/src/bls_chia/agg.rs
  • pkgs/pkc/src/bls_ietf/mod.rs
  • pkgs/pkc/src/bls_chia/mod.rs
  • pkgs/pkc/src/common/bls/contract.rs
  • pkgs/pkc/bench/bls_chia.rs
  • pkgs/pkc/src/bls_ietf/sk.rs
  • pkgs/pkc/tests/bls_ietf_llmq.rs
  • pkgs/pkc/tests/bls_chia_aggregate.rs
  • pkgs/pkc/src/common/mod.rs
  • pkgs/pkc/tests/bls_chia_llmq.rs
  • pkgs/pkc/tests/bls_chia_threshold.rs
  • pkgs/pkc/tests/bls_chia_ser.rs
  • pkgs/pkc/tests/bls_chia_keygen.rs
  • pkgs/pkc/src/bls_ietf/pk.rs
  • pkgs/pkc/tests/bls_ietf_aggregate.rs
  • pkgs/pkc/src/bls_chia/threshold.rs
  • pkgs/pkc/tests/bls_chia_sign.rs
  • pkgs/pkc/src/bls_ietf/agg.rs
  • pkgs/pkc/src/common/bls/mod.rs
  • pkgs/pkc/tests/bls_ietf_sign.rs
  • pkgs/pkc/tests/bls_ietf_threshold.rs
  • pkgs/pkc/src/bls_ietf/threshold.rs

Comment thread pkgs/pkc/bench/bls.rs
Comment thread pkgs/pkc/src/bls/scheme_ietf.rs
Comment thread pkgs/pkc/src/bls/secret_ops.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Crypto

Development

Successfully merging this pull request may close these issues.

1 participant