Expand description
Large-stack execution guard for lattice signing/keygen.
ML-DSA (the FIPS 204 module-lattice signature) allocates large intermediate
working sets on the stack inside the upstream ml-dsa crate: the hedged
signing path expands the public matrix A and buffers several polynomial
vectors through its rejection-sampling loop, and key generation / verifying-key
expansion do the same. Those arrays are fixed-size stack allocations in code we
do not control (ml-dsa), so they cannot be boxed onto the heap from this
crate.
On runtimes with a small thread stack this overflows and faults the guard page. The two constrained runtimes we ship into have different characteristics:
-
BEAM dirty-CPU scheduler (via the Elixir NIFs): the dirty scheduler thread’s default stack (
+sssdcpu, ~320 KB) is far too small and the whole VM dies with SIGBUS. This module provides the fix: run the operation on a dedicated worker thread with a generous stack and block the scheduler on the join — exactly the kind of bounded, blocking work dirty schedulers exist for. -
Browser WASM (via [
crate::wasm]): the shadow stack is a fixed, build-time size with no threads, so the fix there is a linker stack-size bump rather than a worker thread. That is why this module is gated#[cfg(not(target_arch = "wasm32"))]— see the crate’s.cargo/config.tomlfor the WASM side.
Every consumer that drives ML-DSA signing or keygen from a small-stack native
thread should route the call through on_signing_stack rather than
re-implementing the guard or pushing a +sssdcpu requirement onto its own
vm.args. Verification uses far less stack and does not need this.
Constants§
- RECOMMENDED_
SIGNING_ STACK_ BYTES - Recommended stack size, in bytes, for a thread that runs ML-DSA signing or key generation.
Functions§
- on_
signing_ stack - Run
fon a dedicated worker thread withRECOMMENDED_SIGNING_STACK_BYTESof stack, returning its value.