HashSigs RHDL privacy-sanitized source narrative Evidence record: production-signer-generated-rtl-finite Repository-relative source: evidence/rtl/wots-production-signer-generated-verilog-2026-07-15.md Cryptographic subject/source commit: dbd18593527673be2a93d7067ee03667892c582a Cryptographic source dirty: no Pre-sanitization narrative SHA-256: 29ec13e5de12f04e4aafe3b5ed2f0de6959b7a8c248a4d47c7c2ed63adaf8bac Narrative checkout commit: 3810cf837ea79ca005f4ab227b0b5c2134fe6ad1 Narrative checkout dirty: no Sanitization substitutions: environment home-directory path: 1 -> [local-home-path]; home-directory path: 1 -> [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 generated-Verilog equivalence — 2026-07-15 ## Evidence tier and boundary Generated-Verilog deterministic simulation. The externally composed production signer bundle matched twelve independent `Sha256GenericWots` oracle results and passed the finite reset, saturation, framing, backpressure, result-credit, and quiescence checks described below. This is lowering-equivalence evidence for one deterministic finite trace. It is not a formal proof, a sustained-throughput measurement, synthesis, timing, placement, routing, LUT/register/BRAM/DSP utilization, side-channel evidence, or U280 execution evidence. In particular, the source-model throughput remains a model until the later Vivado and card gates pass. ## Reproduction ```console cargo run --release --locked -j1 -p rhdl-gen -- check --signer-full \ --temp-root "[local-home-path]" --keep ``` The command exited with status 0 after 1,003.21 seconds. The preserved workspace is `[local-home-path]`. The path is host-local; the checksums below identify the exact immutable files. The driver lowered the full RHDL SHA-256 lane in one child process, waited for that process to exit, then lowered the unresolved RHDL signer skeleton in a second process. This prevents the two multi-gigabyte RHDL graphs from occupying one address space at the same time. The driver then validated and linked the two read-only sources before invoking Verilator. No generated Verilog was hand-edited. ## Provenance - Source commit: `dbd18593527673be2a93d7067ee03667892c582a` - Source dirty: `false` - Profile: `HASHSIGS_SHA256_GENERIC_V1` - RHDL revision: `c99d5cc53269a247bbc675d0fbd766991d409f56` - HashSigsRS revision: `2d315dd4168804b7cbc51c51a1bf7ca27bf74140` - Verilator: `5.048 2026-04-26 rev v5.048` - Generator version: `0.1.0` - Lint and native-build concurrency: one thread The bundle manifest derives, rather than hand-codes, packed interface widths: signer clock/reset 2 bits, input 547 bits, output 677 bits; lane clock/reset 2 bits, input 801 bits, output 289 bits. ## Immutable artifacts | Artifact | Size / lines | SHA-256 | |---|---:|---| | Full lane RTL | 1,001,581 bytes / 28,223 | `615a4e89519a5aadec2bc17a6b59833fd4bf51dc123f44d378e6f0fb7866610d` | | Signer skeleton RTL | 2,009,645 bytes / 61,538 | `caa554e1b0eed1431038a7c816b7dc9a2b6e9a55377a1caa27d69ab0a02b0087` | | Linked signer bundle | 3,011,226 bytes / 89,761 | `41fe7ba31ec811b6a69ebcb9d2e76af512b0b49af99b7c83389d5cf97b978e68` | | Bundle manifest | 2,232 bytes | `3cebfb959a50f6405952f8005f185dc7077c0bdfc1f251b1ba39661fe150c054` | | Self-checking testbench | 295,695 bytes / 913 | `f7fc208510018b428440025dd1f84c3e18cbf33016d4d24c8ab8cf7e7b0d4733` | | Lane lowering log | 501 bytes | `0cc9c8fb9a4ab44effa813cf36bacf2aa8001d5a10e215e1fb6b9a9def5d4379` | | Skeleton lowering log | 511 bytes | `8e00e82c62276d6a2a294783ddc3d8771bca1bd95366ced5558003ffa9e967ba` | | Verilator lint log | 2,920,748 bytes | `3d68bfcbbccf7eff90b2a3b66019ec9b18a71f884ba39251fc81fdf691a67c56` | | Verilator build log | 29,100 bytes | `5fa603f189402d380449822f4d432eb62b484b1098a453906b0df547b8c0ee77` | | Verilator simulation log | 597 bytes | `2bb980e2e1e75a5921984ed14036b5e7fb65dc60e54b9be4cc16f9d2667e18fa` | | Final evidence manifest | 1,830 bytes | `5fb20020be4957b0d2fa83d77a42529e59bd2cc2da05a36cc9bd308a8a90b467` | The final evidence manifest independently binds the source commit, profile, PASS marker, bundle manifest, testbench, both lowering logs, and all three Verilator logs. A root-side recomputation matched every recorded digest and byte length; all files in the table were mode `0444` after completion. Read-only permissions plus checksums detect ordinary mutation; they are not filesystem-enforced immutability. The manifest does not hash the generator executable itself. This run mitigates stale-binary risk through the observed locked Cargo build and the parent/child source-commit checks, but a future artifact format should bind an executable or embedded build-commit digest too. ## Structural result The linked bundle contains 233 Verilog module definitions. Graph traversal from `wots_sha256_signer_top` found one reachable cluster-instance parent, `wots_sha256_signer_top_clusters`, containing exactly `c0`, `c1`, and `c2` and no extra or duplicate prototype sites. The shared cluster prototype reaches one canonical unresolved lane site. The skeleton contains no lane definition; the final bundle contains exactly one `sha256_compression_lane` definition. Unreachable lookalike modules cannot satisfy this gate. The checker reasons over module-definition reachability rather than a complete elaborated-instance graph. An independent artifact audit therefore also traced the effective hierarchy and confirmed exactly three cluster-prototype paths and three full-lane paths. It confirmed that the bundle bytes are exactly the lane source followed by the skeleton source, with no third edited fragment. This structural result proves the intended generated-source composition. It does not prove how Vivado will map the three instances physically. ## Lint and simulation results Verilator lint/elaboration passed in 109.461 seconds. The accepted warning inventory is 8,397 total: - 5,500 `UNUSEDSIGNAL`; - 2,858 `UNUSEDPARAM`; - 26 `CASEINCOMPLETE`; - 6 `CMPCONST`; - 6 `UNOPTFLAT`; and - 1 `DECLFILENAME`. The `-Wno-fatal` result is accepted elaboration, not a warning-clean claim. The six `UNOPTFLAT` reports name RHDL packed feedback envelopes. Passing the finite simulation does not dispose of them; Vivado synthesis, timing, and combinational-loop DRC are mandatory before any FPGA claim. The current gate records the full warning inventory but does not enforce a code-specific warning allowlist, so a new warning category would be preserved in evidence rather than rejected automatically. The timed native build passed in 539.708 seconds. Simulation passed in 83.939 seconds with this exact marker: ```text WOTS_SHA256_SIGNER_RTL_EQUIVALENCE_PASS jobs=12 beats=420 reset_flush=1 saturation=12 final_hold=5 faults=0 ``` The finite trace: - accepts a sacrificial job and resets it while live; - requires 80 cycles of post-reset silence before new work; - fills all twelve signer contexts and rejects a thirteenth offer while full; - distributes the twelve accepted jobs exactly four per cluster and holds the rejected offer for eight cycles without accidental acceptance; - compares twelve distinct fused signature/public-key frames with the independent software oracle; - checks exactly 35 beats per result and 420 beats total, including job and admission-cluster identity and no interleaving within a frame; - applies deterministic output stalls and requires ready/valid data stability; - holds the first final beat for five cycles; - requires exactly twelve finals and releases, with no reported faults; and - requires exactly four releases per cluster and 160 cycles of final quiescence. As an independent cross-check of the embedded Rust-oracle vectors, the audit reconstructed every signature and public key with Python `hashlib`. All twelve 2,208-byte fused results matched the testbench data. The trace reported first acceptance at cycle 180, last delivery at cycle 6,665, an inclusive-work span reported by the testbench as 6,486 cycles, 69 stalled output cycles, and twelve releases. These are finite-trace observations, not a steady-state signatures-per-second measurement. Verilator is a two-state simulator, so this result is not a four-state unknown-propagation proof. ## Promotion decision and next gate The production signer is promoted from source-simulation and render-only status to the generated-Verilog tier for this exact trace and commit. The previous failed run is retained separately: it stopped on an overstrict structural assertion that assumed direct top-level cluster instances, before external lint or simulation. The repaired gate accepts intervening generated wrappers but still requires exact graph reachability and cardinality. The next evidence tier is an isolated U280 Vivado synthesis run, followed by placement/routing at 4.000 ns and 3.333 ns. Those runs must preserve this exact source/RTL provenance, inspect the six lint feedback paths, and report LUTs, registers, BRAM/URAM, DSPs, WNS/TNS, route status, and the normalized throughput calculation. No resource, timing, or 500,000-signatures/second claim is made by this page.