Repository navigation
Conversation
|
@codex review |
|
bugbot run |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a99f786bcd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}") | ||
| foreach(_mlkem_native_config IN ITEMS DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) | ||
| set(CMAKE_ASM_FLAGS_${_mlkem_native_config} "${CMAKE_C_FLAGS_${_mlkem_native_config}}") |
There was a problem hiding this comment.
Preserve caller-supplied assembler flags
When native assembly is enabled, these assignments overwrite the CMAKE_ASM_FLAGS and configuration-specific values initialized by CMake, including values explicitly supplied by a toolchain, the ASMFLAGS environment variable, or -DCMAKE_ASM_FLAGS=.... For example, configuring with -DCMAKE_ASM_FLAGS=-DUSER_ASM_FLAG leaves that value in the cache but omits it from the mlkem_native_asm.S compile command. This can discard required target, sysroot, or hardening flags and break or weaken affected builds; preserve the existing ASM flags while adding the desired C flags instead.
Useful? React with 👍 / 👎.
| PQ_AARCH64_FILES = frozenset( | ||
| { | ||
| ".github/workflows/ci-pq.yml", |
There was a problem hiding this comment.
Include all ML-KEM wiring in the PQ gate
The allowlist omits several files that now control ML-KEM integration, including the root and src/ CMake files, src/util/CMakeLists.txt, .github/workflows/ci.yml, and the classifier itself. A later PR that changes only one of those files—for example, removing the library link from src/CMakeLists.txt or breaking the reusable-workflow call—will produce pq_aarch64_required=false, so pq-aarch64 is skipped and the full-validation gate explicitly accepts that skip. Add all ML-KEM build and gate wiring paths to this classification so the stated AArch64 requirement cannot be bypassed by an isolated wiring change.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit a99f786. Configure here.
a99f786 to
2d56c6e
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d56c6e628
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| name: macOS arm64 unit tests | ||
| needs: resolve-source | ||
| if: ${{ needs.resolve-source.outputs.run_macos_arm64_unit == 'true' }} | ||
| runs-on: macos-14 |
There was a problem hiding this comment.
Move the PQ job off the retiring macOS 14 image
The newly added macos-arm64-unit job targets macos-14, but GitHub has scheduled macOS 14 runner brownouts beginning October 5, 2026 and full retirement on November 2, 2026. Because an empty/default ci-pq.yml dispatch selects this job, those PQ runs will intermittently fail now and will stop running entirely after retirement, independently of the code under test. Use a supported Apple Silicon label such as macos-15 or macos-26 and update the workflow contract assertion accordingly. See GitHub's macOS 14 retirement announcement.
Useful? React with 👍 / 👎.
2d56c6e to
729f6c0
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3a6f3548f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if(MSVC) | ||
| set(_mlkem_native_arch "MSVC") | ||
| else() | ||
| mlkem_native_detect_arch(_mlkem_native_arch) |
There was a problem hiding this comment.
Include appended flags in architecture detection
When a build uses the supported APPEND_CFLAGS/APPEND_CPPFLAGS variables for target-changing options—for example -m32, paired with the analogous C++ flags—this probe runs without them and detects the host as x86_64, enabling QBIT_MLKEM_NATIVE. The actual ML-KEM C and assembly compilations receive the appended flags later, see an i386 target, and fail in mlkem_config.h because the selected native backend no longer matches. Run the architecture probes with the same effective appended flags as the target, or otherwise base the policy on the final compilation target.
Useful? React with 👍 / 👎.
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Vendor mlkem-native v2.0.0 (d1b2fe782888bdb761a50336012923180be7f502): the whole upstream mlkem/ directory and LICENSE, byte for byte, in src/mlkem-native. Nothing compiles it yet. contrib/devtools/mlkem-native.pin records the commit, tag, the tree id of mlkem/ and the LICENSE blob id. contrib/devtools/update-mlkem-native.sh reproduces the tree from upstream and rewrites the pin from the fetched object ids. test/lint/mlkem-native-check.sh, run by the subtree lint, proves offline that HEAD still holds exactly the pinned tree. Lints that scan src/ ignore the vendored tree, and doc/subtrees/mlkem-native.md is the runbook. Part of #184 (part 3, #190, D1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the XGETBV instruction out of sha256.cpp into compat/cpuid.h as
XGetBV(), next to GetCPUID(). SHA256AutoDetect keeps its own selection
logic unchanged; it calls the shared primitive only.
Add compat/cpu_features.{h,cpp} with a standalone answer to "can this
CPU and OS run AVX2 code": the supported leaves are queried first, XCR0
is read only once leaf 1 reports OSXSAVE and AVX, and AVX2 is usable only
with XMM and YMM state enabled and the leaf 7 AVX2 bit set. Unlike the
SHA256 logic it does not depend on SSE4 or SHA-NI.
HasMlkemX86Native() adds the other extensions that mlkem-native's x86_64
assembly executes, found by auditing the assembled object: SSSE3,
SSE4.1, POPCNT and BMI2. A virtual machine can show AVX2 while hiding
those, and checking AVX2 alone would then end in SIGILL. Both checks
detect once and cache the result, because the ML-KEM capability hook
asks about a hundred times per operation. Non-x86 targets and compilers
without <cpuid.h> report false.
Part of #184 (part 3, #190, D2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SHA256AutoDetect selects the SSE4 code whenever CPUID leaf 1 reports SSE4.1, and only under that check also the 4-way SSE4.1 code and the SHA-NI code. All three execute SSSE3 instructions. An audit of the built objects finds pshufb and palignr in the SSE4 and SHA-NI code and pshufb in the 4-way code, besides SSE4.1's pinsrd, pextrd and pblendw; no SSE4.2 instruction occurs. A virtual machine can report SSE4.1 while masking SSSE3, and the self-test then dies with SIGILL at startup. Require SSSE3 as well. Under qemu-x86_64, -cpu Haswell,-ssse3 and the SHA-NI model EPYC,-ssse3 die with SIGILL before this change and select the standard implementation after it. Unmasked, Haswell still selects sse4, sse41 and avx2, and EPYC and Denverton x86_shani. This is an upstream Bitcoin Core bug, so the change is kept minimal enough to go upstream. Part of #184 (part 3, #190). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build the vendored mlkem-native as ML-KEM-1024 into bitcoin_node only, behind a small C++ wrapper. Nothing in qbitd calls it yet. - src/crypto/mlkem_config.h configures the library (MLK_CONFIG_FILE): parameter set 1024, the qbit_mlkem1024 prefix, deterministic APIs only, zeroization through memory_cleanse, and a capability hook. - Native backends are chosen by qbit-owned backend headers instead of upstream's compile-time defaults, which enable x86_64 only for AVX2 compilers. No source is compiled with an ISA flag: every native entry point asks the hook, which reads only cached CPU detection and one atomic portable override. On x86_64 that detection requires every extension the assembly executes (AVX2, SSSE3, SSE4.1, POPCNT, BMI2), not only the AVX2 that upstream's capability name says. - Upstream's AArch64 single-lane Keccak entry point skips the hook, so the override could not reach it. qbit mirrors that header's dispatch glue with the check added; every other entry point checks itself. - mlkem::KeyGen, CheckPublicKey, Encaps and Decaps take fixed-size spans, map upstream's invalid-key results separately from internal failures, and clear their outputs on every failure. GetBackendNames() reports the implementation that runs. ForcePortableForTesting and InjectResultForTesting are test-only guards. - cmake/mlkem-native.cmake adds WITH_MLKEM_NATIVE=AUTO|ON|OFF and the configure summary line. The library gets core_interface's hardening flags but not qbit's C++ warnings, then APPEND_CPPFLAGS and APPEND_CFLAGS, so the MSan jobs' -U_FORTIFY_SOURCE applies to it as to the other C libraries. MSVC builds without assembly, MSan builds portable C, and AArch64 ELF targets build portable C because the upstream assembly has no BTI landing pads or GNU property note and would strip BTI/PAC marking from the binary (doc/subtrees has the evidence and the revisit trigger). ON fails where native is impossible. mlkem_tests covers NIST ACVP keygen, encapsulation, decapsulation and key checks, all 1040 C2SP CCTV modulus vectors and the 3328/3329 boundary, implicit rejection against an independent SHAKE256, injected failures, moves and wiping, and backend selection, each on the native backend and with portable C forced. ci/checks/test_mlkem_build_policy.py checks the WITH_MLKEM_NATIVE matrix, builds the library with each compiler found (core-checks requires the AArch64 cross compiler), and counts assembly calls to show that the portable override reaches every x86_64 routine. Part of #184 (part 3, #190, D3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add two fuzz targets over the mlkem:: wrapper: - mlkem: honest key generation, encapsulation and decapsulation agree; an arbitrary encapsulation key is accepted exactly when an independent modulus check passes, and a rejected one leaves no output; any ciphertext of the right length decapsulates to a secret that differs from the honest one (implicit rejection is never proof of validity); an arbitrary decapsulation key is rejected exactly when an independent SHA3-256 hash check fails, and the secret is then cleared. - mlkem_backend_diff: the detected backend and forced portable C give equal statuses and outputs for the same inputs, and the override is restored afterwards. Both honor MLKEM_FORCE_PORTABLE=1. They join the required qbit corpus with nine generated seeds each (CCTV modulus key and 3328/3329/4095 coefficients, NIST ACVP decapsulation vectors, a ciphertext bit flip). CI replays them a second time with MLKEM_FORCE_PORTABLE=1 and includes them in the mutation phase; the PQ CI contract test checks that wiring. UBSan's -fsanitize=integer checks are suppressed for the vendored tree, as for the other external libraries. Part of #184 (part 3, #190, D5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Benchmark ML-KEM-1024 key generation, encapsulation and decapsulation twice each: on the detected backend and with portable C forced. Like the per-implementation SHA256 benchmarks, each is named after the backend that ran, so on an AVX2 host bench_qbit -filter='MLKEM.*' lists both, and the portable guard restores auto-detection afterwards. Part of #184 (part 3, #190, D5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add two jobs to the PQ workflow, selectable by name like aarch64-unit: - s390x-unit cross-compiles only test_bitcoin for big-endian s390x on the x64 runner, with Ubuntu's g++-s390x-linux-gnu and the depends tree, and runs the suites through ctest with qemu-s390x as the crosscompiling emulator, so only the tests run emulated. It stays out of the merge gate. Its timeout is 180 minutes until runs are measured. - macos-arm64-unit runs natively on a GitHub-hosted macos-14 runner without Docker, asserts that uname -m is arm64, and shares the unit job's source checks and evidence report through YAML anchors. It is the job that runs native AArch64 ML-KEM, and configures with WITH_MLKEM_NATIVE=ON so that losing native code fails it. All three jobs now expect mlkem_tests besides bip324_tests and net_tests (CTEST_REGEX ^(mlkem_tests|bip324_tests|net_tests)$), and report the suites through ctest_evidence.py. The aarch64 job's description says that ML-KEM runs portable C on AArch64 Linux. The PQ CI contract test covers selecting each job, the s390x cross and emulator settings, the macOS architecture check and report, and that every expression uses a context GitHub makes available there (no runner in job env, no matrix in a job without one), which GitHub enforces when loading the file. Part of #184 (part 3, #190, C2 and the CI part of D3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge-profile classifier gains a pq_aarch64_required output, true when a change touches the ML-KEM library (src/mlkem-native, src/crypto/mlkem*, cmake/mlkem-native.cmake), the v2 transport (src/bip324*, src/net.h, src/net.cpp), the CPU feature checks, the PQ workflow or its env files, or the PQ test suites and vectors. A path it cannot read also requires the job. Full Validation calls ci-pq.yml with jobs: aarch64-unit on the change itself (a pull request's merge commit) when the output is true. The gate accepts a skipped job only when the classifier says it is not required; a required job that was skipped, failed or cancelled, or a missing or unreadable classifier output, fails it. The changed-file lists that feed the classifier, in Full Validation and in the Required Merge Gate, use --no-renames, so moving a file out of a gated path still names it. ci/checks/test_pq_merge_gate_contract.py runs the real classifier, job condition, ci-pq selection step and gate script: a pull request touching src/bip324.cpp requires and runs the job, while docs-only and other source pull requests skip it and pass, and a rename out of a gated path still requires it. The Required Merge Gate runs it with the other PQ CI contracts. Part of #184 (part 3, #190, C3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GitHub is retiring the macos-14 runner image: brownouts start on 2026-10-05 and the image is removed on 2026-11-02. Move the macos-arm64-unit job to macos-15, which is also Apple Silicon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
APPEND_CPPFLAGS and APPEND_CFLAGS reach mlkem_native's C and assembly compiles, but the architecture probes ran without them. A build that appends a target-changing flag such as -m32 was detected as x86_64, enabled the native backend, and then failed in mlkem_config.h. Run the probes with the appended flags, and probe afresh on every configure, since those flags may change between configures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No pull request ever built or ran ML-KEM's native code on macOS: the macos-arm64-unit job could only be dispatched, and nothing ran the x86_64 native code on an Intel Mac at all. Apple Silicon and Intel macOS are release targets with native code enabled. ci-pq.yml gains a macos-x86_64-unit job on GitHub's Intel image (macos-15-intel), sharing every step with macos-arm64-unit. Both build with WITH_MLKEM_NATIVE=ON, check the runner's architecture, and after the suites pass require the native backend by name from mlkem_tests/backend_selection, so a runner whose CPU lacks an extension cannot pass on portable C. Full Validation's PQ job, renamed pq-unit, now calls ci-pq.yml with aarch64-unit, macos-arm64-unit and macos-x86_64-unit, so all three are required exactly when the classifier says the change needs them. The classifier output is renamed pq_unit_required to match. On-demand runs accept the new job name; an empty jobs input runs it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The build-policy test counted assembly calls only for the x86_64 backend, so nothing in CI showed that the portable override reaches every AArch64 assembly routine. With upstream's x1 Keccak glue in place of qbit's mirror, 221 assembly calls ran with portable C forced, and every test passed: outputs agree, and the backend name comes from the hook. The counting harness now also runs on AArch64: a static binary built with aarch64-linux-gnu-g++, from a copy of mlkem_config.h without the AArch64 ELF refusal, and run under qemu-aarch64. A negative control builds upstream's x1 glue and requires the leaked calls to show. Each entry point also runs alone on a new thread while portable C is forced, and must make no assembly call: one that skipped BeginOperation() would run on the new thread's stale copy of the override. The earlier round trip could not show this, since KeyGen set the copy for the whole thread. The build smoke job installs g++-aarch64-linux-gnu and qemu-user and lists them as required, so the AArch64 case cannot skip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two wrapper mutations passed every test. An entry point without BeginOperation() went unnoticed because ForEachBackend calls GetBackendNames() on the same thread first, which takes the override for it. A shared (not thread_local) copy of the override went unnoticed because only one thread ran operations. every_entry_point_takes_the_override runs each entry point alone on a new thread with portable C forced, then asks the capability hooks what that thread's copy says. override_copy_is_per_thread lets one thread take the override set while another holds it unset, and checks that the first thread's copy did not change. override_changed_by_another_thread now runs operations on two threads at once, so a shared copy also gives wrong outputs on x86_64 and a data race under ThreadSanitizer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI replays the mlkem and mlkem_backend_diff targets a second time with MLKEM_FORCE_PORTABLE=1, but nothing checked that the binary honored it: any other value, such as "true", silently selected native code, and the second replay would have repeated the first. Initialize now refuses any value but unset, empty, 0 or 1, prints the active backend once, and aborts when MLKEM_FORCE_PORTABLE=1 but the active backend is not portable/portable. A host without native code also shows in the log, where mlkem_backend_diff compares portable C with itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SHA256AutoDetect requires SSSE3 besides SSE4.1 before it selects its SSE4, SSE4.1 or SHA-NI code, all of which execute SSSE3 instructions. Nothing tested that: dropping the SSSE3 term passed every test, because real SSE4.1 hardware always has SSSE3. An overload of SHA256AutoDetect takes the CPUID and XGETBV functions, as cpu_features::DetectX86Features does, and the existing one passes the real ones, so the queries and the selection are unchanged. A cpu_features_tests case runs it on synthetic CPUs derived from this one: unmasked it selects what this CPU gets, and with SSSE3 or SSE4.1 masked the standard code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The wrapper's header said native code runs on "x86_64 with AVX2, AArch64", and the WITH_MLKEM_NATIVE help text spoke of "the x86_64 and AArch64 ML-KEM assembly". AArch64 runs native code only on macOS (AArch64 ELF builds stay portable to keep their BTI and PAC marking), and x86_64 also needs SSSE3, SSE4.1, POPCNT and BMI2, as cpu_features::HasMlkemX86Native checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
update-mlkem-native.sh fetched the upstream release with --depth=1 into the qbit repository itself. That writes .git/shallow, so a full clone then reported itself as shallow to git and every tool that asks. Fetch into a temporary bare repository instead, and read the commit, the object ids and the archive from there. Staging and the byte-for-byte check still run in the qbit repository. Re-vendoring v2.0.0 by tag and by commit leaves no diff, and the clone stays complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#190 asks for ELF property evidence that linking the x86_64 assembly keeps the CET marking. Record what a local Ubuntu build shows: the assembly and C objects and the test_qbit and fuzz binaries that link the native backend all carry IBT and SHSTK, the binaries need only baseline x86-64, and the assembly loses its note only when built with -fcf-protection=none. The Guix release evidence is still outstanding and is required before the post-quantum feature branch merges into 1.x.x. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
every_entry_point_takes_the_override captured a structured binding in the thread's lambda, which compilers accept only from C++20 (P1091R3, P1381R1). Bind the label and the entry point to ordinary variables, so the test does not depend on that support. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first macOS arm64 run failed to compile txmempool.h: with NO_DEPENDS=1 the job used Homebrew's Boost, now 1.92, and Boost 1.91 stopped accepting a struct derived from multi_index::indexed_by as an index list. Bitcoin Core fixed the source in bitcoin/bitcoin#35175; that backport is handled on its own. Build Boost and libevent with depends, natively for the runner, so the jobs compile against the versions qbit releases with. Homebrew now installs GNU Make 4 for depends instead of the two libraries. A step sets HOST and reads depends' own build id (packages, recipes and compilers), which keys an actions/cache of depends/built. It is saved once the toolchain file exists, even if the suites fail. After the build, a step requires that depends built that id and that CMake took the toolchain, libevent and Boost at boost.mk's version from it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c32c65d to
df22737
Compare
Summary
Part 3 of #184. Closes #190. Stacked on #224, the foundations.
This vendors mlkem-native v2.0.0 unmodified and builds ML-KEM-1024 into
bitcoin_nodebehind a small C++ wrapper. Native code runs where it is proved, supported and keeps the binary's hardening; portable C runs everywhere else. Nothing inqbitdcalls the library yet; the handshake is part 4.src/mlkem-native/holds upstream's wholemlkem/directory andLICENSEatd1b2fe782888bdb761a50336012923180be7f502, byte-identical.contrib/devtools/mlkem-native.pinrecords the upstream tree and blob ids, andupdate-mlkem-native.shreproduces the tree.test/lint/mlkem-native-check.shfails on any drift.doc/subtrees/mlkem-native.mdis the runbook.cpu_features::HasMlkemX86Native()is detected once and cached. It requires exactly the ISA extensions the vendored x86_64 assembly uses: AVX2 with OS YMM state, SSSE3, SSE4.1, POPCNT and BMI2. An instruction audit of the assembled object confirmed that list. A VM that exposes AVX2 but masks BMI2 or POPCNT now runs portable C instead of hitting SIGILL. Only the XGETBV primitive moved out ofsha256.cpp.SHA256AutoDetectnow also requires SSSE3 for the SSE4, 4-way SSE4.1 and SHA-NI paths, which all executepshufb. A CPU or VM that reports SSE4.1 without SSSE3 used to die with SIGILL in the startup self-test (reproduced under qemuHaswell,-ssse3andEPYC,-ssse3). This is an upstream Bitcoin Core bug; the change is minimal so it can go upstream.src/crypto/mlkem.{h,cpp}has fixed-size types; secret outputs are cleared on every failure, and the invalid-public-key result is kept apart from internal failure.x1_scalar.hhas no capability check. It calls the same upstream assembly.CMAKE_ASM_FLAGS,ASMFLAGSor toolchain values and add the C flags in front. On MinGW, the assembler flag that rewrites aligned vector moves no longer reaches the vendored assembly.WITH_MLKEM_NATIVE=AUTO|ON|OFFand a truthful configure-summary line. MSan and MSVC builds are portable-only.bitcoin_nodeonly.APPEND_CPPFLAGS/APPEND_CFLAGSreach its C and ASM compiles, as for secp256k1.mlkemandmlkem_backend_difftargets are registered in the required qbit corpus with seeds, honorMLKEM_FORCE_PORTABLE, and the forced-portable replay runs in CI.bench_qbithas one benchmark per backend.s390x-unit(big-endian; tests run through ctest's emulator setting) andmacos-arm64-unit(withWITH_MLKEM_NATIVE=ON) joinci-pq.yml. All PQ unit jobs now requiremlkem_tests,bip324_testsandnet_teststo have run and passed.src/, tests, fuzz, bench), CI wiring, the classifier itself or vectors must passaarch64-unit. A contract test fails if any CMake, workflow orci/file that mentions ML-KEM isn't covered.full-validation-gateacceptsskippedonly when the classifier says the job isn't required.Testing
test_qbit,bench_qbitandfuzz, with every commit built and tested on its own.mlkem_tests(NIST ACVP ML-KEM-1024 keyGen and encapDecap, C2SP CCTV modulus vectors, implicit rejection, wrapper lifetimes, backend selection), native and forced-portable with identical outputs;cpu_features_tests,crypto_tests,bip324_tests,net_tests;Haswell,-bmi2,-popcnt,-sse4.1,-ssse3) run portable with no SIGILL;ci/checks/test_mlkem_build_policy.py: the AUTO/ON/OFF matrix across architectures, compilers and sanitizers, with cross builds for aarch64 and MinGW. It counts wrapped assembly calls and fails if any runs when portable is forced;ci/checkscontract tests, each new rule caught by a mutation;feature_segwit.pymypy error, which comes from a newer local mypy.s390x-unitandmacos-arm64-unit: on-demand dispatch ofci-pq.ymlneeds themaincaller from test, ci: foundations: qbit release tooling, Python ML-KEM-1024, v1.0.0 interop, PQ CI workflow, canary tools (#184 part 2) #186's C4.qbitdandtest_qbitkeepIBT, SHSTKandx86-64-baselinebefore and after.Two independent adversarial reviews, one on crypto and build and one on CI, accepted this with fixes, all folded in here.
--wrapharness proved the portable override reaches every assembly entry point. It found the missing BMI2/POPCNT requirement (now fixed) and the MSan flag issue (now fixed).runner.tempuse that GitHub rejects (now fixed).Target Branch
1.x.x, stacked on test, ci: foundations for hybrid v2 transport (Python ML-KEM, qbit releases, v1.0.0 interop, PQ CI, canary tools) #224.Risk / Review Notes
Notes:
-m32), so none can be skipped.Docs / Process Impact
doc/subtrees/mlkem-native.md,doc/development/fuzzing.mdandtest/lint/README.md.Closes #190 · Part of #184
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.