Random coin for the STARK verifier, built on a Poseidon2 sponge.<br /><br />The sponge state is stored in memory as three words: rate R1 (r1_ptr), rate R2 (r2_ptr),<br />and capacity C (c_ptr). R1 and R2 are contiguous (r2_ptr = r1_ptr + 4), so rate elements<br />0..7 can be addressed as r1_ptr + index.<br /><br />Sampling uses an output_len counter that tracks how many rate elements remain. Each<br />permutation sets output_len=8; each sample_felt decrements it by 1 and reads<br />rate[output_len - 1].<br /><br />Two absorption paths are provided:<br />- `observe_felt`/`flush_buffer`: a faithful buffered duplex matching p3's `DuplexChallenger`<br />(append to `rate[input_len]`, permute only once the rate fills, flush a partial buffer<br />lazily). Used for the public inputs, instance shape, and main-trace commitment, whose<br />element stream is not rate-aligned.<br />- `reseed_direct`/`reseed_with_felt`/etc.: rate-aligned absorptions that write directly to<br />rate memory and permute immediately. Valid only when the input buffer is empty (the stream<br />is known to start and end on a rate boundary).<br />
## miden::core::stark::random_coin
| Procedure | Description |
| ----------- | ------------- |
| get_rate_1 | Return the first half of the rate portion of the random coin state.<br /><br />Input: [...]<br />Output: [R1, ...]<br />Cycles: 6<br /> |
| set_rate_1 | Store the first half of the rate portion of the random coin state.<br /><br />Input: [R1, ...]<br />Output: [...]<br />Cycles: 6<br /> |
| get_rate_2 | Return the second half of the rate portion of the random coin state.<br /><br />Input: [...]<br />Output: [R2, ...]<br />Cycles: 6<br /> |
| set_rate_2 | Store the second half of the rate portion of the random coin state.<br /><br />Input: [R2, ...]<br />Output: [...]<br />Cycles: 6<br /> |
| get_capacity | Return the capacity portion of the random coin state.<br /><br />Input: [...]<br />Output: [C, ...]<br />Cycles: 6<br /> |
| set_capacity | Set the capacity portion of the random coin state.<br /><br />Input: [C, ...]<br />Output: [...]<br />Cycles: 6<br /> |
| load_random_coin_state | Load the random coin state on the stack.<br /><br />Input: [...]<br />Output: [R0, R1, C, ...]<br />Cycles: 18<br /> |
| store_random_coin_state | Store the random coin state to memory.<br /><br />Input: [R0, R1, C, ...]<br />Output: [...]<br />Cycles: 18<br /> |
| add_absorb_length_tag | Add the absorbed-length tag to the first capacity element (sponge state element 8).<br /><br />Mirrors p3's `DuplexChallenger::duplexing`, which makes every absorb prefix-free by<br />binding the number of absorbed elements into the capacity before permuting. Squeeze-only<br />permutations (empty input buffer) carry no tag.<br /><br />Input: [n, ...]<br />Output: [...]<br /> |
| sample_felt | Sample a single base field element from the transcript.<br /><br />SAFETY: Requires output_len > 0. All call sites in the recursive verifier guarantee this<br />invariant because every sponge permutation sets output_len=8 and at most 8 elements are<br />consumed before the next permutation. An assertion guards against caller bugs.<br /><br />Input: [...]<br />Output: [x, ...]<br /> |
| sample_ext | Sample a quadratic extension field element from the transcript.<br /><br />Input: [...]<br />Output: [x0, x1, ...]<br /> |
| sample_bits | Sample a number of bits from the transcript.<br /><br />Input: [bits, ...]<br />Output: [value, ...]<br /> |
| observe_felt | Absorb a single base field element into the transcript via the buffered duplex.<br /><br />Mirrors p3's `DuplexChallenger::observe`: invalidates any buffered rate output<br />(`output_len = 0`), appends the element at `rate[input_len]`, and permutes only once the buffer<br />fills (`input_len == 8`). A partial buffer is duplexed lazily by `flush_buffer`, which callers<br />must run before sampling; until then `sample_felt`'s `output_len > 0` assertion fails loudly<br />rather than returning a stale rate element.<br /><br />Input: [felt, ...]<br />Output: [...]<br /> |
| flush_buffer | Flush a partial input buffer, matching the `DuplexChallenger` duplexing performed at sample time.<br /><br />When the input buffer is non-empty, permute the sponge: the buffered prefix already occupies<br />`rate[0..input_len]`; `rate[input_len..8]` is zeroed and the absorbed length is bound into<br />the capacity, exactly as p3's prefix-free absorb does before permuting. Exposes a fresh<br />output (output_len=8) and empties the buffer. No-op when the buffer is already empty.<br /><br />Input: [...]<br />Output: [...]<br /> |
| init_seed | Initializes the random coin state with domain-separated Fiat-Shamir (DSFS) seeding,<br />then derives trace domain parameters.<br /><br />Implements the transcript initialization:<br /><br />Use the caller-supplied RELATION_DIGEST as initial sponge capacity,<br />absorb PCS parameters into the rate, and permute.<br />Rate layout: R1 = [nq, query_pow_bits, deep_pow_bits, folding_pow_bits]<br />R2 = [log_blowup, log_final_degree, fold_arity, 0]<br /><br />RELATION_DIGEST = hash(PROTOCOL_ID, CIRCUIT_COMMITMENT) is a compile-time constant<br />computed once per AIR and pushed by the caller (the specific verifier).<br /><br />Currently assumes a blowup factor equal to 8.<br /><br />Precondition: num_queries, query_pow_bits, deep_pow_bits, and folding_pow_bits must<br />already be stored in memory before calling this procedure.<br /><br />Input: [log(core_trace_length), log(chiplets_trace_length), rd0, rd1, rd2, rd3, ...]<br />Output: [...]<br /> |
| observe_instance_shape | Observe the multi-AIR instance shape into the Fiat-Shamir transcript via the buffered duplex.<br /><br />Mirrors the framework's `observe_shape`, which observes the instance count followed by the<br />per-AIR log trace heights in instance order (Core, then Chiplets):<br />[ 2, log(core trace height), log(chiplets trace height) ].<br /><br />These continue the same buffered duplex begun by `process_public_inputs`, so no permutation is<br />forced here; `reseed_main_after_shape` appends the main-trace commitment and flushes.<br /><br />Input: [...]<br />Output: [...]<br /> |
| reseed_main_after_shape | Observe the main-trace commitment and flush the buffered duplex.<br /><br />Appends the commitment word `[c0, c1, c2, c3]` to the buffered transcript stream (continuing<br />from the instance shape) and then flushes any partial buffer, matching the DuplexChallenger's<br />duplex at the first post-commitment sample (auxiliary randomness). On exit: output_len=8.<br /><br />Input: [c0, c1, c2, c3, ...]<br />Output: [...]<br /> |
| reseed_with_felt | Reseed with a commitment word and absorb an additional single felt, then permute.<br /><br />Writes the commitment word to rate[0..3] and the felt to rate[4], zeroes rate[5..7],<br />binds the absorbed length (5) into the capacity, then permutes. Used in the FRI layer<br />loop where each round absorbs a layer commitment plus a PoW nonce felt.<br /><br />SAFETY:<br />1. input_len=0 (asserted).<br />2. On exit: input_len=0, output_len=8 (fresh permutation output).<br /><br />Input: [felt, w0, w1, w2, w3, ...]<br />Output: [...]<br /> |
| reseed_direct | Reseed by writing a word directly to rate[0..3] and permuting.<br /><br />Overwrites rate[0..3] with the given word, zeroes rate[4..7], binds the absorbed<br />length (4) into the capacity, then permutes. This is the standard absorb-and-permute<br />pattern for a single word.<br /><br />SAFETY:<br />1. input_len=0 (asserted).<br />2. The word to absorb is on top of the stack.<br />3. On exit: input_len=0, output_len=8 (fresh permutation output).<br /><br />Input: [w0, w1, w2, w3, ...]<br />Output: [...]<br /> |
| sample_folding_pow_and_ext | Verify per-round FRI folding proof-of-work and sample one extension field element,<br />reading rate elements directly instead of going through `sample_felt`.<br /><br />Reads rate[7] (grinding), rate[6] and rate[5] (ext element) from r2_ptr memory,<br />matching what `sample_felt` would return at output_len=8,7,6.<br /><br />The folding PoW bit count is read from memory (set by load_security_params).<br />When folding_pow_bits=0 the check is trivially satisfied (mask=0).<br /><br />Equivalent to: `get_folding_pow_bits sample_bits assertz; sample_ext`<br /><br />SAFETY:<br />1. MUST be called immediately after `reseed_with_felt` with no intervening<br />random coin operations (output_len=8, input_len=0 guaranteed).<br />2. Sets output_len=5 on exit (3 elements consumed), input_len=0 unchanged.<br />3. folding_pow_bits must already be stored in memory.<br /><br />Input: [...]<br />Output: [a0, a1, ...]<br /> |
| generate_aux_randomness | Draw a list of random extension field elements related to the auxiliary segment of the execution<br />trace and store them.<br /><br />More specifically, we draw two challenges, alpha and beta. This means that our multi-set hash function<br />has the form `h(m) = alpha + \sum_{i=0}^{\|m\| - 1} m_i * beta^i` for a message `m`.<br /><br />As these random challenges have already been used non-deterministically in prior computations, we<br />also check that the generated challenges match the non-deterministically provided one.<br /><br />Input: [...]<br />Output: [...]<br />Cycles: 20<br /> |
| generate_constraint_composition_coefficients | Draw constraint composition random coefficient and save it at `compos_coef_ptr`.<br /><br />Input: [...]<br />Output: [...]<br />Cycles: 13<br /> |
| generate_deep_composition_random_coefficients | Draw deep composition polynomial random coefficient and save it at `deep_rand_coef_ptr`.<br /><br />As this random challenge has already been used non-deterministically in prior computations, we<br />also check that the generated challenge matches the non-deterministically provided one.<br /><br />Input: [...]<br />Output: [...]<br />Cycles: 22<br /> |
| generate_z_zN | Generate the OOD challenge point `z = (z0, z1)` and compute `z^N` where N is<br />the trace length. The resulting word `[(z_0, z_1)^N, z0, z1]` is stored in the<br />global memory address `exec.z_ptr` reserved for it.<br /><br />Input: [X, ...]<br />Output: [...]<br />Note: The top word on the stack is consumed by this procedure.<br />Cycles: 21 + 10 * log(N)<br /> |
| generate_list_indices | Generate a list of `num_queries` number of random indices in the range<br />[0, lde_size) and store it in memory starting from `query_ptr`.<br />The list is stored as `(index, depth, index, 0)` where `index` is the sampled domain-order<br />index and `depth` is `log(lde_domain_size)`, which is needed when computing the DEEP queries.<br /><br />Reads rate elements directly from memory (decrementing from output_len-1 down to 0),<br />permuting when the rate is exhausted, rather than calling sample_felt per query.<br /><br />Input: [...]<br />Output: [...]<br /><br />NOTE: This procedure is called right after the PoW check. The PoW check consumes one<br />rate element via sample_bits, leaving output_len = 7.<br /> |
| check_deep_pow | Check the DEEP proof-of-work.<br /><br />Called before sampling DEEP composition polynomial challenges.<br /><br />SAFETY: Requires input_len=0.<br /><br />Input: [...]<br />Output: [...]<br /> |
| check_query_pow | Check the query proof-of-work.<br /><br />Called after loading the FRI remainder, before sampling query indices.<br /><br />SAFETY: Requires input_len=0 (guaranteed after load_and_verify_remainder).<br /><br />Input: [...]<br />Output: [...]<br /> |