HashSigs RHDL privacy-sanitized source narrative Evidence record: production-signer-generated-rtl-sustained Repository-relative source: evidence/rtl/wots-production-signer-sustained-throughput-2026-07-15.md Cryptographic subject/source commit: dbd18593527673be2a93d7067ee03667892c582a Cryptographic source dirty: no Flow commit: 276c538fbc4d316a610f673121dd7476e6c2a25d Pre-sanitization narrative SHA-256: ba8b922426016731718028a39302ad42c909d55e4a4085876d7cb92b53e50208 Narrative checkout commit: 3810cf837ea79ca005f4ab227b0b5c2134fe6ad1 Narrative checkout dirty: no Sanitization substitutions: home-directory path: 2 -> [local-home-path] This public projection is not byte-identical when substitutions are listed. The digest identifies the pre-sanitization narrative bytes read by this documentation build. It does not assert that those bytes existed at the cryptographic subject commit. --- sanitized narrative --- # WOTS production signer sustained generated-RTL throughput — 2026-07-15 ## Evidence tier and boundary Generated-Verilog deterministic sustained simulation. The preserved production signer bundle completed 72 distinct `Sha256GenericWots` oracle jobs under continuous admission and an always-ready output. The measured 48-result steady interval was 23,121 cycles, or 481.6875 cycles/result. Normalized at 250 MHz, that is 519,008.693 results/second. This proves the cycle interval only for this exact generated RTL, deterministic workload, and always-ready trace. It is not a formal proof, four-state proof, synthesis, timing closure, resource mapping, placement, routing, power, side-channel, shell/card, or U280 execution result. The normalized rate becomes a hardware throughput claim only after the same RTL meets the stated clock in Vivado and on the target integration. ## Reproduction ```console cargo run --release --locked -j1 -p rhdl-gen -- signer-throughput \ --source-evidence \ [local-home-path] \ --output \ [local-home-path] ``` The command exited with status 0. The clean Rust release build preceded the gate. The gate revalidated the complete prior finite-equivalence evidence chain before the Verilator build, again before simulation, and after simulation. It did not lower, relink, or edit RHDL-generated Verilog. Verilator used `--threads 1 -j 1`. Its native build passed in 422.304 seconds; simulation passed in 364.881 seconds. The preserved output directory above is host-local, so the digests below are the durable identities. ## Provenance - Throughput-flow commit: `276c538fbc4d316a610f673121dd7476e6c2a25d` - Flow dirty at execution: `false` - Flow executable: 8,877,496 bytes, `52b47f88742732394dfec71401372591b9bbc78f1b603d0b8aec51d899e20412` - Source RTL commit: `dbd18593527673be2a93d7067ee03667892c582a` - Profile: `HASHSIGS_SHA256_GENERIC_V1` - Verilator: `5.048 2026-04-26 rev v5.048` - Generator version: `0.1.0` - Source finite-equivalence marker: ```text WOTS_SHA256_SIGNER_RTL_EQUIVALENCE_PASS jobs=12 beats=420 reset_flush=1 saturation=12 final_hold=5 faults=0 ``` The final manifest binds the clean flow commit and executable digest in addition to the source commit, linked bundle, both source manifests, prior PASS marker, new testbench, simulator, build log, simulation log, Verilator version, and benchmark constants. ## Immutable artifacts | Artifact | Size / lines | SHA-256 | |---|---:|---| | Linked source signer bundle | 3,011,226 bytes / 89,761 | `41fe7ba31ec811b6a69ebcb9d2e76af512b0b49af99b7c83389d5cf97b978e68` | | Source bundle manifest | 2,232 bytes | `3cebfb959a50f6405952f8005f185dc7077c0bdfc1f251b1ba39661fe150c054` | | Source check-evidence manifest | 1,830 bytes | `5fb20020be4957b0d2fa83d77a42529e59bd2cc2da05a36cc9bd308a8a90b467` | | Sustained testbench | 1,678,172 bytes / 3,104 | `1548fae5438db555b01ebcffb090579ecb08d9e574638a24681366d74ad2b08a` | | Verilator simulator | 9,749,160 bytes | `9a48b01e0186bc26fea0380af5ee13be6d065b44ee14a78c103b5d5b34569754` | | Verilator build log | 30,896 bytes / 210 | `700cc61b268ea51507b69e89be7f4d9761c87d030755ebeeeb8fb95625dc0a20` | | Verilator simulation log | 721 bytes / 11 | `5912f045ac5ea0231639aa1a01205f796770239ddd6d76754d000f605e69890b` | | Final throughput manifest | 3,044 bytes | `99c6e9c1eb6e93731e1fe8aa53a633ae61df3a3109d2075136a8fd6cd0a00c33` | The testbench, logs, and manifest are mode `0444`; the simulator is mode `0555`. Root-side recomputation matched every digest recorded by the manifest. Read-only permissions plus checksums detect ordinary mutation; they are not a substitute for immutable storage. ## Exact measurement The simulation emitted exactly one measurement record and exactly one PASS marker: ```text WOTS_SHA256_SIGNER_RTL_SUSTAINED_MEASUREMENT boundary12=6418 boundary60=29539 elapsed=23121 measured_results=48 total_cycles=35148 beats=2520 releases=72 WOTS_SHA256_SIGNER_RTL_SUSTAINED_THROUGHPUT_PASS jobs=72 warmup=12 measured=48 tail=12 max_elapsed=24000 max_cycles_per_result=500 output_ready=1 faults=0 ``` The normalized calculation is: ```text cycles/result = 23,121 / 48 = 481.6875 results/s at 250 MHz = 250,000,000 * 48 / 23,121 = 519,008.693 ``` The trace is 879 measured cycles inside the 24,000-cycle limit, equivalent to 18.3125 cycles/result of headroom. The normalized rate is 3.8017% above the 500,000-results/second target. At 300 MHz the same measured interval would mathematically normalize to 622,810.432 results/second, but no 300 MHz timing claim is made here. This gate bounds the average over that single aggregate 48-result interval. It does not claim that each of the 48 individual inter-completion intervals is at most 500 cycles. The preserved PASS marker's `max_cycles_per_result` field is the historical name of this aggregate-average budget. ## Trace coverage The self-checking testbench: - embeds 72 distinct fused signature/public-key results from the independent Rust oracle, with distinct one-time private seeds, messages, and job IDs; - holds each next input valid continuously until admission and keeps output ready asserted throughout; - checks all 2,520 output beats, exactly 35 per job, with no frame interleaving and exact job, admission-cluster, and output-cluster identity; - checks 72 final beats and 72 local credit releases; - permits at most one pending release and requires its cluster to match the next delivered final; - uses results 1–12 as warm-up, measures boundaries 12–60, then requires all 12 tail results; and - requires 160 final quiescent cycles with no fault, error, duplicate, malformed, or unexpected output. Verilator is a two-state simulator. The successful build retained 43 nonfatal warnings: 26 `CASEINCOMPLETE`, 6 `CMPCONST`, 6 `UNOPTFLAT`, and 5 `WIDTHEXPAND`. The inventory is preserved in the build log. This is successful elaboration and execution, not a warning-clean claim; Vivado DRC and timing remain mandatory, especially for the generated feedback paths named by `UNOPTFLAT`. ## Promotion decision and next gate The production signer is promoted to sustained generated-RTL throughput evidence for the exact always-ready trace: it clears the user-specified 500,000-results/second normalized target at 250 MHz. The next evidence tier is isolated U280 Vivado synthesis and implementation of the provenance-bound signer RTL. It must prove LUTs at or below 200,000, registers at or below 300,000, DSPs at or below 4,000, complete routing, and nonnegative setup/hold timing at the selected clock. Until then, this page does not claim mapped resources, 250/300 MHz timing closure, or FPGA throughput.