Skip to main content

Module sign_core

Module sign_core 

Source
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:

The whole signer (profile 15/11/3/1) requestM + tag 11 SHA-512 ringsH(prefix‖M) 3 scalar ringsr = H mod l 15 fixed-base machines[r]B, 392 instr. 1 compress machineencode 32 R at once SHA rings againk = H(R‖A‖M) scalar rings againS = k·a + r signatureR‖S + tag Every arrow is a ready/valid handshake. A request is admitted only with a reserved compress slot (a "credit"), which is what makes the shared rings deadlock-free. 2,048 credits keep about 1,800 signatures in flight.

§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_BATCH points 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_ready requires 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

  1. Admission: take a free context and a credit, store M and the user tag, start SHA-512(prefix || M) (kind nonce).
  2. Scalar ring: r = digest mod l; r is stored for step 5.
  3. Fixed-base machine: [r]B, then either affine conversion in the same machine (fused, NCP = 0) or batch conversion in the compress stage.
  4. The encoding R is stored and SHA-512(R || A || M) starts (kind challenge).
  5. Scalar ring: S = k * a + r mod l.
  6. Output R || S with 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§

ScalableSignCore
Resource-scalable cached-key Ed25519 signer with 2^CB sign contexts (CB <= 11; CTX_BITS for the throughput profiles).
ScalableSignIn
Public input of ScalableSignCore.
ScalableSignOut
Public output of ScalableSignCore.
SignMems
Controller memories (all inferred BRAM), each 2^CB deep and indexed by sign context, except free_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.
SignMemsIn
Port bundle of SignMems.
SignMemsOut
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 CB parameter of ScalableSignCore may be smaller. Context fields in registers and tags stay 11 bits wide regardless of CB; they are resized to CB only 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‖M is 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 R from canonical affine y and the sign of x.
idle_table_write
No key-table write.
nonce_block
Big-endian SHA words of prefix || M with padding (96-byte message).
ram_read
Memory port that reads addr and writes nothing.
recode_mixed
Signed mixed-radix recoding (super::host::recode) of a scalar below 2^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 a TB = 9 table scanner.