feat(math-cuda): RPX256 permutation kernel source + host known-answer harness (lane K, phase 1) - #952
Merged
Merged
Conversation
…wer harness An #[ignore]d integration test that prints, as C++ source, the tables crypto/math-cuda/tests/host_kat/rpx_kat_vectors.h embeds: the bare RPX permutation on ten states (all-zero, all-(p-1), 0..12, alternating, two one-hot lanes, four seeded random), the rate-8 overwrite-duplex leaf at lengths 0, 1, 7, 8, 9, 16 and 17 felts, and two parents. miden publishes no RPX known-answer table, so lfm::rpx::Rpx256 is the oracle the device kernel is pinned to. Outputs are canonical; inputs are derived from fixed seeds and printed alongside them so the header stays self-contained data.
…nswer harness Lane K, phase 1 of the per-table GPU redo: kernels/rpx.cu carries the Rescue-Prime eXtended (XHash12) permutation over Goldilocks at width 12, the rate-8 overwrite-duplex leaf sponge and the Merkle parent, written to compile both under nvcc and on the host through cuda_host_shim.h. No launch code, no build.rs/lib.rs wiring yet (phase 2; src/rpx.rs is a documented placeholder that nothing compiles). The oracle is the Rust host implementation, prover/src/lfm/rpx.rs, and the constants are RPO's, transcribed mechanically from rpo.rs. The MDS ports rpo.rs's u128-accumulation property: one reduction per output lane and no per-term field multiplication, assembled on device from two 32-bit half-sums (each below 2^40 because the circulant row sums to 160), so the whole MDS is 288 narrow multiply-adds and 12 reductions. The inverse S-box is miden's 72-step chain (63 squarings, 9 products) per lane; the cubic extension is phi^3 = phi + 1 with each coefficient folded into one three-term dot product, deliberately NOT ext3.cuh's w^3 = 2 product. tests/host_kat/rpx_host_kat.cpp layers its anchoring the way the Rust module does: field primitives against schoolbook __int128 arithmetic; the MDS, both S-boxes and the extension against independent algorithms; seven FB rounds composed into RPO256 and replayed over miden-crypto's nineteen hash_elements vectors (external); and the RPX permutation, leaf sponge and parent against tables printed by the Rust oracle (prover/tests/rpx_host_kat_vectors.rs, run on a box). It also checks raw vs canonical inputs, that RPX is not RPO, that every lane reaches the output, and counts the field operations per round kind so the cost model is a measurement: 2736 multiplications, 144 dot products and 300 adds plus 7 MDS per permutation, against RPO's 6384 and 14.
MauroToscano
force-pushed
the
pt/rpx-kernel
branch
from
September 7, 2026 18:52
b66977a to
50c633e
Compare
Same shape as test-blake3-host-kat: host compile of the kernel source through the shim, then run. Lane K's harness; the Makefile is the coordinator's file.
This was referenced Sep 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane K, phase 1 of the per-table GPU redo (EXECUTION step 4): the RPX256 / XHash12 permutation as CUDA kernel source that also compiles on the host through the Track G shim, plus the host known-answer harness. New files only; no
build.rs/lib.rs/device.rs/lde.rs/fri.rs/ Makefile edits (those are requests below).Files
crypto/math-cuda/kernels/rpx.cu—rpx::permute(scheduleFB E FB E FB E M),rpx::Sponge+rpx::sponge_leaf(rate-8 OVERWRITE duplex, capacity lane 8 =len mod 8, lane 9 ="LFML"),rpx::compress(one permutation of[l ‖ r ‖ 0⁴]). Constants are RPO's ARK1/ARK2/MDS row, transcribed by script fromrpo.rs. Output is canonicalised so digests matchdigest_to_commitmentbytes.crypto/math-cuda/tests/host_kat/rpx_host_kat.cpp— the harness (make test-rpx-host-katonce the Makefile target lands; see request 1).crypto/math-cuda/tests/host_kat/rpx_kat_vectors.h— data: miden-crypto's 19 RPOhash_elementsvectors (external) + the three Rust-oracle tables.prover/tests/rpx_host_kat_vectors.rs—#[ignore]d generator that prints the oracle tables fromlfm::rpx::Rpx256,algebraic_commit::sponge_leaf,HasherKind::Rpx.compress.crypto/math-cuda/src/rpx.rs— phase-2 placeholder, deliberately not declared inlib.rs.Oracle and anchoring
The oracle is
prover/src/lfm/rpx.rsbyte for byte. The harness layers its anchoring the way that module's own provenance note does: (1) field primitives vs schoolbook__int128; (2) MDS vs its per-term definition, S-boxes vs generic exponentiation (incl.x^INV_ALPHA), cubic extension vs naive polynomial arithmetic modφ³ − φ − 1; (3) external: sevenfb_round<R>composed = RPO256, replayed over miden's 19 vectors — pins ARK1/ARK2, MDS row + orientation, both S-box chains, the sponge lane convention; (4) the Rust oracle: permutation (10 states incl. all-zero, all-(p−1)), leaf at 0/1/7/8/9/16/17 felts, two parents; (5) negative controls (RPX ≠ RPO, every lane reaches the output, raw[p, 2^64)inputs ≡ canonical, outputs canonical); (6) op counts measured.The u128 MDS property (
rpo.rs:527-536) is ported, not rediscovered: one reduction per output lane, no per-term field multiply; the device assembles the same 73-bit integer from two 32-bit half-sums (each≤ 160·(2^32−1) < 2^40), so the MDS is 288 single32×32→64MACs + 12 reductions.Gate (host compile, laptop, Makefile's
HOST_KAT_CXXFLAGS)Before the oracle tables were pasted, the same binary reported exactly the five expected
FAILlines for the three empty tables and nothing else. The generator ran on box A at 824d678 (release):test result: ok. 1 passed; 0 failed.cargo check -p lambda-vm-prover --test rpx_host_kat_vectors: clean, 32.7 s.Op counts (measured by the harness; MDS static)
x^7x^{1/7}ext_mulInverse S-box = 2592 / 2736 of the field multiplications.
Requests to the coordinator
test-rpx-host-katto the.PHONYlist (line 6, aftertest-blake3-host-kat) and, after thetest-blake3-host-katrecipe (~line 623):make linton a box (laptop rule): expect the only Rust delta,prover/tests/rpx_host_kat_vectors.rs, to be clean;cargo fmt --allalready ran.build.rsgetscompile_kernel("rpx.cu", "rpx.cubin", have_nvcc, &[])(+rerun-if-changed),lib.rsgetspub mod rpx;. Until then nothing compilesrpx.cuunder nvcc.Open risks
__device__ __constant__arrays,__device__ constexprscalars, templated__device__functions,#pragma unroll), but the first cubin build is phase 2's.inv_sbox(72-deep chain × 12 lanes) and the dynamic index inSponge::absorbare phase-2 measurements (-Xptxas -v).