Expand description
The controller: how requests flow through the engines, and why the flow cannot deadlock.
ScalableSignCore instantiates NFB fixed-base machines, NSHA
SHA-512 rings, NSC scalar rings and NCP (0 or 1) batch-compress
machines, and moves every request through them:
§Handshakes and parking
Every arrow is a ready/valid handshake. A producer that cannot hand off
parks: rings keep the finished job circulating, machines retry their
OUT bundle. Nothing is dropped and no queue can overflow.
§Credits: the deadlock argument
The SHA-512 and scalar rings are shared by the first half of signing
(nonce hash, r) and the second (challenge hash, S). Without care, the
loop SHA → scalar → fixed-base → compress → SHA can fill up and stop.
The rule that prevents it: a request is admitted only with a credit, a
reserved batch-compress slot (in fused mode, a fixed-base context),
returned when the request leaves that stage. With its slot reserved,
every fixed-base output has somewhere to go, the fixed-base machines always
drain, and every remaining wait points strictly downstream.
§Credits: the throughput limit
A credit is held from admission until its compress batch retires: about 12.5k cycles of fixed-base program (392 bundles × 32 contexts), 27k of batch compression (423 bundles × 64 contexts) and ~8k of hashing, queueing and filling. By Little’s law the credit pool caps throughput at credits ÷ hold time: with 2,048 credits, about one signature per 23 cycles. (With the first design’s 1,024 credits and longer hold, the cap was ~44 cycles, which is why 12/6/2/1 and 13/8/2/1 measured 45.7 and 44.1 however many machines they had.)
§Contexts
Messages, r, R and user tags live in BRAM indexed by a sign context.
There are 2^CB contexts: CTX_BITS = 11 (2,048) for throughput
profiles; Ed25519SignCore uses 7, since fused
mode never admits more than 32 · NFB requests.
§Other behaviour
- Fixed-base outputs fill one compress batch of
COMPRESS_BATCHpoints at a time; a partial batch is flushed after 64 idle cycles when enough credits remain to pay for its empty slots, so a trickle still completes. - Key expansion uses the same SHA ring, scalar ring and fixed-base
machine;
load_key_readyrequires an idle signer with no key loaded. - Scalars are recoded in hardware by
recode_mixed. - A single request takes ~22k cycles on 1/1/1/0 and ~45–50k on 15/11/3/1; throughput needs many requests in flight.
§Job tags
Every SHA-512, scalar, fixed-base and compress job carries a 16-bit tag:
bits 15..11 are the job kind (KIND_NONCE = 0, KIND_CHALLENGE = 1,
KIND_KEY = 2) and bits 10..0 the sign context. A completion therefore
says which step finished and where its request’s state lives, so no
engine needs to finish in order. Key jobs use context 0; they only run
while no request is in flight, so they cannot collide with a request.
§Steps of one request
- Admission: take a free context and a credit, store
Mand the user tag, startSHA-512(prefix || M)(kind nonce). - Scalar ring:
r = digest mod l;ris stored for step 5. - Fixed-base machine:
[r]B, then either affine conversion in the same machine (fused,NCP = 0) or batch conversion in the compress stage. - The encoding
Ris stored andSHA-512(R || A || M)starts (kind challenge). - Scalar ring:
S = k * a + r mod l. - Output
R || Swith the user tag and return the context.
Key loading runs the same engines with kind key: SHA-512(seed),
a mod l, [a]B, and the encoding becomes the cached public key.
Re-exports§
pub use crate::compress_stage::COMPRESS_BATCH;pub use crate::compress_stage::COMPRESS_CONTEXTS;pub use crate::compress_stage::CpMachine;
Structs§
- Scalable
Sign Core - Resource-scalable cached-key Ed25519 signer with
2^CBsign contexts (CB <= 11;CTX_BITSfor the throughput profiles). - Scalable
Sign In - Public input of
ScalableSignCore. - Scalable
Sign Out - Public output of
ScalableSignCore. - Sign
Mems - Controller memories (all inferred BRAM), each
2^CBdeep and indexed by sign context, exceptfree_list, which is indexed by FIFO position. Every read has one cycle of latency, which is why several stages wait a cycle (has_msg,needs_r,has_tag) before using read data. - Sign
Mems In - Port bundle of
SignMems. - Sign
Mems Out - Read data of
SignMems, valid one cycle after the read address.
Constants§
- CTX_
BITS - Sign-context index width of the throughput profiles (2048 requests in
flight); the
CBparameter ofScalableSignCoremay be smaller. Context fields in registers and tags stay 11 bits wide regardless ofCB; they are resized toCBonly at the memory ports.
Functions§
- challenge_
block - Big-endian SHA words of
R || A || M(first of two blocks). - challenge_
second_ pad - The challenge hash needs the ring’s second (padding) block:
R‖A‖Mis exactly 128 bytes for a 64-byte message. - digest_
le - Digest (big-endian state words) to the little-endian 512-bit integer.
- digits15_
to_ words - Fifteen digits to four little-endian words.
- encode_
point - Encoded
Rfrom canonical affineyand the sign ofx. - idle_
table_ write - No key-table write.
- nonce_
block - Big-endian SHA words of
prefix || Mwith padding (96-byte message). - ram_
read - Memory port that reads
addrand writes nothing. - recode_
mixed - Signed mixed-radix recoding (
super::host::recode) of a scalar below2^253: digits 0..39 are radix 32, 39..54 radix 16, sign-magnitude (bit 5 = sign); entries 54..64 are zero. - scalable_
sign_ kernel - State transition for
ScalableSignCore. - seed_
block - Padded single block of a 32-byte seed.
- sign_
mems_ kernel - Wiring for
SignMems: ports pass straight to the six BRAMs. - widen_
digits - Base-point digits in slots 0..64 of the machine’s 128 digit slots.
- words_
to_ digits15 - Four little-endian words (bits 0..255) to fifteen digits (bit 255 dropped).
- words_
to_ digits31 - Little-endian 64-bit words to thirty-one 17-bit digits.
Type Aliases§
- FbMachine
- Fixed-base machine: 32 contexts (
KB = 5), a 1024-bundle program ROM (PB = 10) and aTB = 9table scanner.