Repository navigation
pkc%test(bls): add the programs that write the BLS corpora - #112
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 32 minutes. View limit details
No actionable comments were generated in the recent review. Summary
Merge Risk:
|
|
Note This pull request has no conflicts! 🎊 🎉 🎊 |
|
✅ Final review complete — no blockers (commit 5e0c21a) |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 1 + Phase 2
Static verification of the exact base-to-head range, pinned reference sources, regeneration driver, and nine generators found no actionable defects; no Rust library sources or committed corpora change. Current lint, stable builds, cross-builds, and dash-pkc MSRV checks pass, while additional MSRV/platform jobs remain pending; the displayed failures in “Tag pull requests” and “Comment on pull requests” are cancelled administrative jobs with no steps, not code failures. No builds or tests were run in this static-only lane, so byte-identical corpus regeneration and Nix-shell execution were not independently confirmed.
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This substantial change adds corpus-generation programs and build tooling rather than changing production cryptography or another critical runtime surface. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
8505bf4 to
fa6c595
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Static verification of the complete diff at fa6c595 found no actionable in-scope defects; the changes add reference-backed corpus tooling without modifying Rust library code or committed corpora. The pinned reference sources support the build approach and generator semantics, and the current output-writing code addresses the historical truncation concern. Current CI shows lint, documentation, stable-platform checks, and two MSRV build/test jobs passing, with additional MSRV and cross-target checks pending; corpus regeneration and the Nix shell were not independently executed.
🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This substantial change adds corpus-generation programs and build orchestration, but does not change production cryptography, consensus behavior, or existing corpora. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.
No unresolved findings remain from the prior review on this head.
kwvg
left a comment
There was a problem hiding this comment.
Rebase on latest develop to incorporate base-sdk#111
|
Thanks for the review. I'll take all of it, including switching the generator build to CMake with the template patched back in, so Autotools stays out of the dev shell. I'm rebasing on 🤖 Posted autonomously by Claude on behalf of pasta. |
Pinned at v24.0.0-rc.5 for the programs that write the BLS corpora. It is only checked out on request, and Bazel, CodeQL and the crate package skip it, as its tree carries build files of its own.
The C++ programs that write test corpora build with CMake against Boost's headers and GMP. The CI shell includes the module, and the dev shell with it.
fa6c595 to
dbea0b0
Compare
|
Rebased on 🤖 Posted autonomously by Claude on behalf of pasta. |
dbea0b0 to
ccae7d7
Compare
|
Thanks, all taken. In every program, the fixed values move to the top of the file as 🤖 Posted autonomously by Claude on behalf of pasta. |
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The exact-head corpus regeneration, unchanged-output check, and clang lint job passed; this PR changes no production library code or committed corpus data. Static verification confirmed that the new exclusion bypasses CodeQL analysis for all first-party corpus generators, which should be addressed before merging. Lint, MSRV, and several other checks remain pending; the cancelled tagging/commenting jobs are unrelated to code validation.
🔴 1 blocking | 💬 1 nitpick(s)
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This is a substantial, cross-cutting corpus-generation and build-tooling change, but the diff does not change production cryptography or another critical runtime surface. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `maint/lint/lint_codeql.py`:
- [BLOCKING] maint/lint/lint_codeql.py:276-280: Preserve CodeQL coverage for the corpus generators
The new `_UNANALYSED` pathspec excludes every generator and `util/no_random.cpp` from CodeQL extraction, even after regeneration supplies their headers. This defeats the C/C++ analysis introduced by #111 specifically in preparation for corpus generators: it removes all CERT checks, not just diagnostics caused by combining independent executable entry points. The corpus workflow runs clang-tidy after regeneration but never runs CodeQL, so that job does not restore the missing coverage. Keep these first-party units in extraction and address cross-executable diagnostics through target-separated analysis or narrowly matched suppressions using the existing mechanism. Run the analysis after regeneration so its include directories are available.
In `pkgs/pkc/contrib/gen_serialize.cpp`:
- [NITPICK] pkgs/pkc/contrib/gen_serialize.cpp:22: Explain why both serialization arms use legacy signing
The hardcoded `true` is correct: both arms must encode the same G2 point, rather than independently sign with their respective schemes. `ser_pairs()` pairs entries by index, and `signature_serialization_matches_vectors()` checks that the legacy point compresses to the paired IETF entry. Add a short local comment explaining why the signing flag deliberately differs from the serialization flag, so this does not look like an accidental hardcoded scheme.
ccae7d7 to
b9ab99a
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Verified the findings against b9ab99a. The serialization comment addresses the earlier documentation finding, but the blanket CodeQL exclusion still bypasses the existing CERT analysis for all ten new first-party C++ translation units. This was a static review; current-head lint, build, and corpus-workflow checks remain pending, with no completed code-check failure shown.
🔴 1 blocking
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This is a substantial cross-cutting addition of corpus generators, regeneration tooling, and build/CI integration, but it does not change production cryptography or another critical runtime surface. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `maint/lint/lint_codeql.py`:
- [BLOCKING] maint/lint/lint_codeql.py:276-280: Preserve CodeQL coverage for the corpus generators
(existing thread: https://github.com/dashpay/base-sdk/pull/112#discussion_r4454491805)
The planned restoration is not present at this head. `_UNANALYSED` excludes `pkgs/pkc/contrib` before extraction, removing all nine generators and `util/no_random.cpp` even after their generated headers exist. The corpus workflow runs regeneration and clang-tidy but no CodeQL analysis, while the ordinary lint workflow does not regenerate the required headers. Consequently, none of these new first-party translation units receives the existing CERT C++ checks. This blanket bypass weakens the project's static-analysis gate; it is not evidence of an exploitable vulnerability in the generators. The extraction commands compile each unit separately with `-fsyntax-only`, so multiple entry points do not require a linker failure or directory-wide exclusion. Restore these units, run their analysis after regeneration, and address any actual cross-executable diagnostics through target separation or the existing exact path/message suppressions.
Each program links the pinned release's BLS library and writes one corpus. regen.py builds them with CMake and writes the nine corpora, and the C/C++ linters read its last build when there is one.
b9ab99a to
b59f374
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Reviewed the complete diff at b59f374; it changes corpus-generation tooling and configuration, not runtime library code or committed corpora. Both prior findings are addressed, but the new workflow lacks the host configuration required to launch its Nix-wrapped CodeQL. Validation was static only: build and lint checks remain pending, while the two metadata checks shown as failing were cancelled without executing steps.
🔴 1 blocking
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This is a substantial cross-cutting change to corpus-generation programs, build tooling, CI and static analysis, but it does not change production cryptography or another critical surface. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `.github/workflows/build_corpora.yml`:
- [BLOCKING] .github/workflows/build_corpora.yml:121-123: Enable unprivileged user namespaces before running CodeQL
This job runs on ubuntu-24.04 but omits the host setup needed by the Nix-provided CodeQL. `contrib/nix/mods/codeql.nix` wraps Linux invocations in `fhs-run`, whose `buildFHSEnv` implementation launches bubblewrap. Ubuntu's AppArmor restriction on unprivileged user namespaces prevents that Nix-store bubblewrap from starting, so the analysis fails before extracting the generators. The existing lint job handles this requirement in `.github/workflows/build_stable.yml:54-56`. Add an equivalent step using `shell: bash` and `sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0` before invoking CodeQL; the setting must be applied in this job because the other workflow's runner does not share its host configuration.
The job writes the corpora with regen.py, checks them unchanged and lints and analyses the programs against that build, weekly and on changes to the programs, the corpora, their lint setup or Nix shells.
b59f374 to
5e0c21a
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The complete base-to-head static review at 5e0c21a found no actionable in-scope defects: both prior blockers are fixed, and the serialization-documentation nitpick is withdrawn after checking the paired-point consumers. No builds or tests were run locally; current build, lint, and corpus-workflow checks remain pending. The failing “Comment on pull requests” and “Tag pull requests” checks are policy/automation checks, not code-validation failures.
🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
normalbygpt-6.1-sol(effort low) — This is a substantial tooling, corpus-generation, and CI change, but the diff does not change production cryptography or another critical runtime surface. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-3.8-flash-high(antigravity quota lookup failed),glm-5.3-flash(not used above high effort; tier asks max) - Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
- Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort high); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort high); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.
No unresolved findings remain from the prior review on this head.
…plementation does (#101) * [03eefd7] pkc%test(bls): add a program that writes the BLS read corpus (pasta) * [6bff16d] pkc%fix(bls): read legacy G1 `x = 0` with the sign bit set (pasta) * [ac2355f] pkc%fix(bls): accept legacy encodings off the curve in `is_canonical` (pasta) * [137d329] pkc%test(bls): check BLS reads against the reference outcomes (pasta) * [1ebd2c2] pkc%doc: update changelog for the legacy BLS reads (pasta) Description: ````` ## Motivation `dash-pkc` reads BLS bytes at two levels. `to::<S>()` decodes an element, and `is_canonical::<S>()` says whether the scheme reads the bytes as an element that encodes back to them. Under the legacy scheme, the reference implementation accepts three kinds of input that `dash-pkc` refuses: - a public key with `x = 0` with the sign bit set, (0, -2). blst's decompression writes this point out but reports an error; - a public key encoding an `x` below the field prime with no point on the curve, with bits 5-6 clear, under either sign; - a signature encoding an `x` with no point on the curve, with both halves below the field prime and the sign bit and the top three bits of `x.c1` clear. This pull request makes `to::<BlsScChia>()` decode the first kind and `is_canonical::<BlsScChia>()` accept all three. `to` still refuses the off-curve encodings, since there is no point to return for them, and its rustdoc says so. The basic scheme is unchanged, and so is the stray-bit masking on the legacy G1 path. ## Additional Information This pull request is based on `pasta/bls-corpus-gen` (#112), which adds the reference implementation as a submodule and the programs that write the other BLS corpora. | Description | Notes | | ----------- | ----- | | Add a program that writes the BLS read corpus | `gen_read.cpp` builds seeded inputs with relic's field and curve operations and writes `pkgs/pkc/corpus/bls_read.json5`: 79 public-key and 130 signature inputs, each with the library's outcome under the legacy and basic schemes, `null`, `valid` or `invalid`. For each input the legacy scheme reads as valid, relic also gives whether its `x` has a point on the curve. `regen.py` writes it with the other corpora. | | Read legacy G1 `x = 0` with the sign bit set | `to` and `is_canonical` accept it, and it round-trips. With the sign bit clear, stray bits 5-6 mask `x = 0` down to the null encoding, so those bytes still do not decode. Adds `BlsScheme` methods `g1_bytes`, a point in the scheme's 48-byte layout, and `pk_ietf_bytes`, the IETF compressed form of an encoding in that layout; `BlsScChia` moves its legacy encoder and its legacy-to-IETF conversion into them. | | Accept legacy encodings off the curve in `is_canonical` | New `BlsScheme` methods `is_canonical_pk` and `is_canonical_sig` hold each scheme's rule. `BlsScIetf` keeps the previous rule, decode plus byte-exact re-encode. `BlsScChia` also accepts the off-curve encodings. `g2_bytes` is the G2 counterpart of `g1_bytes`, and `sig_ietf_x_bytes` gives the `x` of a G2 encoding in the IETF compressed layout, with the sign bit clear. | | Check BLS reads against the reference outcomes | Every corpus input is checked under both schemes, against `is_null`, `is_canonical` and the scheme's own predicate. `to` must fail for each legacy input the corpus marks off the curve, and decode and re-encode to itself for every other valid input. | | Update the changelog | Under "Changed" for the two read changes, and "Added" for the `BlsScheme` methods. | Each outcome in `bls_read.json5` comes from the release's read of the input: - the all-zero input is `null`; - otherwise the input is `valid` when the library's element reader, under the scheme flag, returns an element other than the identity that encodes back to the input; - anything else is `invalid`. The program is C++ because the library's element readers are its C++ API over relic. `pkgs/pkc/contrib/README.md` has the regeneration recipe. ## Breaking Changes None. `is_canonical::<BlsScChia>()` accepts more inputs and `to::<BlsScChia>()` decodes one more. `BlsScheme` gains six required methods, but the trait is sealed, so no implementation outside `dash-pkc` exists. CI (`just test lint fuzz::test`, CodeQL included) is green on each commit. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional tests - [x] I have made corresponding changes to the documentation - [ ] I did not use agentic assistance (i.e. LLMs, AI) except as [disclosed](#agent-disclosure) and can answer questions, comments and concerns without said assistance. I assume authorship of the code submitted. - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ### Agent disclosure Code, commit messages and this description were generated with Claude Code using Claude Opus 5.5, running autonomously as an agent on behalf of the author. The agent also built the pinned release's BLS library and wrote the corpora with it. The change was reviewed by a Claude Code agent using Opus 5.5 and a Codex agent using GPT-6.1. 🤖 Generated with [Claude Code](https://claude.com/claude-code) `````
Takes dashpay#100 dashpay#88 dashpay#108 dashpay#107 dashpay#111 dashpay#110 dashpay#112 dashpay#115 dashpay#114 dashpay#101. ChainSetup keeps the DEC-1043 policy fields; the BS11 BLS wrappers, i64 TxOut values and MAX_SER_SIZE payload bound stay for Core parity.
…plementation does (dashpay#101) * [03eefd7] pkc%test(bls): add a program that writes the BLS read corpus (pasta) * [6bff16d] pkc%fix(bls): read legacy G1 `x = 0` with the sign bit set (pasta) * [ac2355f] pkc%fix(bls): accept legacy encodings off the curve in `is_canonical` (pasta) * [137d329] pkc%test(bls): check BLS reads against the reference outcomes (pasta) * [1ebd2c2] pkc%doc: update changelog for the legacy BLS reads (pasta) Description: ````` ## Motivation `dash-pkc` reads BLS bytes at two levels. `to::<S>()` decodes an element, and `is_canonical::<S>()` says whether the scheme reads the bytes as an element that encodes back to them. Under the legacy scheme, the reference implementation accepts three kinds of input that `dash-pkc` refuses: - a public key with `x = 0` with the sign bit set, (0, -2). blst's decompression writes this point out but reports an error; - a public key encoding an `x` below the field prime with no point on the curve, with bits 5-6 clear, under either sign; - a signature encoding an `x` with no point on the curve, with both halves below the field prime and the sign bit and the top three bits of `x.c1` clear. This pull request makes `to::<BlsScChia>()` decode the first kind and `is_canonical::<BlsScChia>()` accept all three. `to` still refuses the off-curve encodings, since there is no point to return for them, and its rustdoc says so. The basic scheme is unchanged, and so is the stray-bit masking on the legacy G1 path. ## Additional Information This pull request is based on `pasta/bls-corpus-gen` (dashpay#112), which adds the reference implementation as a submodule and the programs that write the other BLS corpora. | Description | Notes | | ----------- | ----- | | Add a program that writes the BLS read corpus | `gen_read.cpp` builds seeded inputs with relic's field and curve operations and writes `pkgs/pkc/corpus/bls_read.json5`: 79 public-key and 130 signature inputs, each with the library's outcome under the legacy and basic schemes, `null`, `valid` or `invalid`. For each input the legacy scheme reads as valid, relic also gives whether its `x` has a point on the curve. `regen.py` writes it with the other corpora. | | Read legacy G1 `x = 0` with the sign bit set | `to` and `is_canonical` accept it, and it round-trips. With the sign bit clear, stray bits 5-6 mask `x = 0` down to the null encoding, so those bytes still do not decode. Adds `BlsScheme` methods `g1_bytes`, a point in the scheme's 48-byte layout, and `pk_ietf_bytes`, the IETF compressed form of an encoding in that layout; `BlsScChia` moves its legacy encoder and its legacy-to-IETF conversion into them. | | Accept legacy encodings off the curve in `is_canonical` | New `BlsScheme` methods `is_canonical_pk` and `is_canonical_sig` hold each scheme's rule. `BlsScIetf` keeps the previous rule, decode plus byte-exact re-encode. `BlsScChia` also accepts the off-curve encodings. `g2_bytes` is the G2 counterpart of `g1_bytes`, and `sig_ietf_x_bytes` gives the `x` of a G2 encoding in the IETF compressed layout, with the sign bit clear. | | Check BLS reads against the reference outcomes | Every corpus input is checked under both schemes, against `is_null`, `is_canonical` and the scheme's own predicate. `to` must fail for each legacy input the corpus marks off the curve, and decode and re-encode to itself for every other valid input. | | Update the changelog | Under "Changed" for the two read changes, and "Added" for the `BlsScheme` methods. | Each outcome in `bls_read.json5` comes from the release's read of the input: - the all-zero input is `null`; - otherwise the input is `valid` when the library's element reader, under the scheme flag, returns an element other than the identity that encodes back to the input; - anything else is `invalid`. The program is C++ because the library's element readers are its C++ API over relic. `pkgs/pkc/contrib/README.md` has the regeneration recipe. ## Breaking Changes None. `is_canonical::<BlsScChia>()` accepts more inputs and `to::<BlsScChia>()` decodes one more. `BlsScheme` gains six required methods, but the trait is sealed, so no implementation outside `dash-pkc` exists. CI (`just test lint fuzz::test`, CodeQL included) is green on each commit. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional tests - [x] I have made corresponding changes to the documentation - [ ] I did not use agentic assistance (i.e. LLMs, AI) except as [disclosed](#agent-disclosure) and can answer questions, comments and concerns without said assistance. I assume authorship of the code submitted. - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ### Agent disclosure Code, commit messages and this description were generated with Claude Code using Claude Opus 5.5, running autonomously as an agent on behalf of the author. The agent also built the pinned release's BLS library and wrote the corpora with it. The change was reviewed by a Claude Code agent using Opus 5.5 and a Codex agent using GPT-6.1. 🤖 Generated with [Claude Code](https://claude.com/claude-code) `````
* [f3ac1b6] pkc%test(bls): run the legacy map's own steps in `gen_hash.cpp` (pasta) Description: ````` ## Motivation In #101 the program that writes `bls_read.json5` was reworked so that nothing in it stands in for the library. `gen_hash.cpp`, from #112, still repeats the legacy hash to G2's tag hashing and reduction steps with relic and takes only the final point from the library, so nothing showed that the steps it records are the ones the library runs. This pull request is the follow-up agreed in [the #101 review](#101 (comment)). ## Additional Information | Description | Notes | | ----------- | ----- | | Give two steps of the legacy map external linkage | `pkgs/pkc/contrib/util/legacy_steps.patch` gives the release's legacy map's encoding of a field element and its cofactor multiplication external linkage. Their code is unchanged. `regen.py` applies it after the relic template patch, and the build directory's name now covers both patches, so a build from before is not reused. | | Check the recorded steps against the library | For each message, `gen_hash.cpp` runs those two steps on the four field elements it writes, as the map does: the encodings of the two pairs, their sum and its cofactor multiple. The program stops, writing nothing, unless the result is the library's own map of the message. The hashing and reduction are still repeated with relic, as the map computes them inline. | The check ties every `_hash` and `_fp` value to the library except the order of the two pairs of tags, since the sum of their encodings is the same either way. `pkgs/pkc/contrib/README.md` says so. ## Breaking Changes None. No library code changes, and `bls_hash.json5` is unchanged. ## How Has This Been Tested? - `regen.py --program hash` extracts and builds the patched release afresh and writes `bls_hash.json5` byte-identical to the committed one, with GCC 15. Only Linux x86_64 was run. - With a wrong byte planted in the tag hashing, the program stops and nothing is written. Swapping the two elements of a pair, negating an element or a pair, and leaving out the cofactor step each stop it too. - The lint suite is clean with the submodule checked out. - CI (`just test lint fuzz::test`) is green on the commit. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional tests - [x] I have made corresponding changes to the documentation - [ ] I did not use agentic assistance (i.e. LLMs, AI) except as [disclosed](#agent-disclosure) and can answer questions, comments and concerns without said assistance. I assume authorship of the code submitted. - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ### Agent disclosure Code, commit messages and this description were generated with Claude Code using Claude Opus 5.5, running autonomously as an agent on behalf of the author. The agent also built the pinned release's BLS library and wrote the corpus with it. The change was reviewed by a Claude Code agent using Opus 5.5. 🤖 Generated with [Claude Code](https://claude.com/claude-code) `````
Motivation
The BLS corpora in
pkgs/pkc/corpusare written from the reference implementation, but the programs that wrote them are not in the repository. This pull request adds them, withregen.pyto write every corpus again from a pinned release, so a corpus can be checked or extended later. It is split out of #101, which adds one more program on top of it.Additional Information
pkgs/pkc/contrib/dash, pinned at v24.0.0-rc.5 (8163290aa0), shallow and withupdate = none, so a clone,git submodule updateand CI checkouts skip it. Onlyregen.pychecks it out. Bazel, CodeQL and the crate package skip it, as its tree carries build files of its own.gen_*.cpplinks the release's BLS library (dashbls, with relic), plus a few of the release's own sources where a corpus needs them, and prints one corpus.regen.pyextracts the release'ssrc, builds the library, compiles and runs every program, and writes the corpora only when all of them succeed. The nine corpora come out byte-identical, so this changes no corpus.pkgs/pkc/contrib/README.mdhas the recipe.contrib/nix/shell/dev.nixgains autoconf, automake, libtool, pkg-config and GMP forregen.py. The CI shell is unchanged.Bazel has no build for the library, and the release's copy of the library builds with autotools only, as the reference implementation stopped tracking relic's CMake configuration template. So
regen.pyruns that build, which needs a POSIX shell, and GMP is required.When these programs were added, the corpora were also checked equal at v23.1.8 (728f505583).
The C++ here is as it was in #101 and predates the clang-format style in #111. As discussed in #101, this branch is open for the C++ lint and static analysis commits. Whichever of this and #111 lands second will adapt.
Breaking Changes
None. No library code changes.
How Has This Been Tested?
regen.pywrites the nine corpora byte-identical to the committed ones, with GCC 15 and with clang 21 building both the library and the programs, from a fresh clone that fetches the submodule and from an existing build.cargo test -p dash-pkc --all-featurespasses, and the lint suite is clean with the submodule checked out.just test lint fuzz::test, CodeQL included) is green on each commit.Checklist
comments and concerns without said assistance. I assume authorship of the code submitted.
Agent disclosure
Code, commit messages and this description were generated with Claude Code using Claude Opus 5.5, running autonomously as an agent on behalf of the author. The agent also built the pinned release's BLS library and wrote the corpora with it. The change was reviewed by a Claude Code agent using Opus 5.5.
🤖 Generated with Claude Code