Skip to main content

miden_ace_codegen/layout/
keys.rs

1use super::InputLayout;
2use crate::EXT_DEGREE;
3
4/// Logical inputs required by the ACE circuit.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum InputKey {
7    /// Public input at the given index.
8    Public(usize),
9    /// Aux randomness α supplied as an input.
10    AuxRandAlpha,
11    /// Aux randomness β supplied as an input.
12    AuxRandBeta,
13    /// Main trace value at (offset, index).
14    Main { offset: usize, index: usize },
15    /// Base-field coordinate for an aux trace column.
16    AuxCoord {
17        offset: usize,
18        index: usize,
19        coord: usize,
20    },
21    /// Aux bus boundary value at the given index.
22    AuxBusBoundary(usize),
23    /// Out-of-domain evaluation point `zeta`.
24    Z,
25    /// Composition challenge used to fold constraints.
26    Alpha,
27    /// `zeta^N`, where `N` is the trace length.
28    ZPowN,
29    /// `g^{-1}`, inverse trace domain generator.
30    GInv,
31    /// `g^{-2}`, squared inverse trace domain generator.
32    GInv2,
33    /// `zeta^(N / max_cycle_len)` for periodic columns.
34    ZK,
35    /// First barycentric weight for quotient recomposition.
36    Weight0,
37    /// `g = h^N`, the chunk shift ratio.
38    G,
39    /// `s0 = offset^N`, the first chunk shift.
40    S0,
41    /// `1 / (zeta - g^{-1})` (selector denominator).
42    InvZMinusGInv,
43    /// `1 / (zeta - 1)` (selector denominator).
44    InvZMinusOne,
45    /// `1 / (zeta^N - 1)` (vanishing inverse).
46    InvVanishing,
47    /// Base-field coordinate for a quotient chunk opening at `offset`
48    /// (0 = zeta, 1 = g * zeta).
49    QuotientChunkCoord {
50        offset: usize,
51        chunk: usize,
52        coord: usize,
53    },
54}
55
56/// Canonical InputKey → index mapping for a given layout.
57#[derive(Debug, Clone, Copy)]
58pub(crate) struct InputKeyMapper<'a> {
59    pub(super) layout: &'a InputLayout,
60}
61
62impl InputKeyMapper<'_> {
63    /// Return the input index for a key, if it exists in the layout.
64    pub(crate) fn index_of(&self, key: InputKey) -> Option<usize> {
65        let layout = self.layout;
66        match key {
67            InputKey::Public(i) => layout.regions.public_values.index(i),
68            InputKey::AuxRandAlpha => Some(layout.aux_rand_alpha),
69            InputKey::AuxRandBeta => Some(layout.aux_rand_beta),
70            InputKey::Main { offset, index } => match offset {
71                0 => layout.regions.main_curr.index(index),
72                1 => layout.regions.main_next.index(index),
73                _ => None,
74            },
75            InputKey::AuxCoord { offset, index, coord } => {
76                if index >= layout.counts.aux_width || coord >= EXT_DEGREE {
77                    return None;
78                }
79                let local = index * EXT_DEGREE + coord;
80                match offset {
81                    0 => layout.regions.aux_curr.index(local),
82                    1 => layout.regions.aux_next.index(local),
83                    _ => None,
84                }
85            },
86            InputKey::AuxBusBoundary(i) => layout.regions.aux_bus_boundary.index(i),
87            InputKey::Z => Some(layout.stark.z),
88            InputKey::Alpha => Some(layout.stark.alpha),
89            InputKey::GInv => Some(layout.stark.g_inv),
90            InputKey::ZPowN => Some(layout.stark.z_pow_n),
91            InputKey::GInv2 => Some(layout.stark.g_inv2),
92            InputKey::ZK => Some(layout.stark.z_k),
93            InputKey::Weight0 => Some(layout.stark.weight0),
94            InputKey::G => Some(layout.stark.g),
95            InputKey::S0 => Some(layout.stark.s0),
96            InputKey::InvZMinusGInv => Some(layout.stark.inv_z_minus_g_inv),
97            InputKey::InvZMinusOne => Some(layout.stark.inv_z_minus_one),
98            InputKey::InvVanishing => Some(layout.stark.inv_vanishing),
99            InputKey::QuotientChunkCoord { offset, chunk, coord } => {
100                if chunk >= layout.counts.num_quotient_chunks || coord >= EXT_DEGREE {
101                    return None;
102                }
103                let idx = chunk * EXT_DEGREE + coord;
104                match offset {
105                    0 => layout.regions.quotient_curr.index(idx),
106                    1 => layout.regions.quotient_next.index(idx),
107                    _ => None,
108                }
109            },
110        }
111    }
112}