halo2_axiom/dev/
metadata.rs

1//! Metadata about circuits.
2
3use super::metadata::Column as ColumnMetadata;
4use crate::plonk::{self, Any};
5use std::{
6    collections::HashMap,
7    fmt::{self, Debug},
8};
9/// Metadata about a column within a circuit.
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Column {
12    /// The type of the column.
13    pub(super) column_type: Any,
14    /// The index of the column.
15    pub(super) index: usize,
16}
17
18impl Column {
19    /// Return the column type.
20    pub fn column_type(&self) -> Any {
21        self.column_type
22    }
23    /// Return the column index.
24    pub fn index(&self) -> usize {
25        self.index
26    }
27}
28
29impl fmt::Display for Column {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(f, "Column('{:?}', {})", self.column_type, self.index)
32    }
33}
34
35impl From<(Any, usize)> for Column {
36    fn from((column_type, index): (Any, usize)) -> Self {
37        Column { column_type, index }
38    }
39}
40
41impl From<plonk::Column<Any>> for Column {
42    fn from(column: plonk::Column<Any>) -> Self {
43        Column {
44            column_type: *column.column_type(),
45            index: column.index(),
46        }
47    }
48}
49
50/// A helper structure that allows to print a Column with it's annotation as a single structure.
51#[derive(Debug, Clone)]
52pub(super) struct DebugColumn {
53    /// The type of the column.
54    column_type: Any,
55    /// The index of the column.
56    index: usize,
57    /// Annotation of the column
58    annotation: String,
59}
60
61impl From<(Column, Option<&HashMap<Column, String>>)> for DebugColumn {
62    fn from(info: (Column, Option<&HashMap<Column, String>>)) -> Self {
63        DebugColumn {
64            column_type: info.0.column_type,
65            index: info.0.index,
66            annotation: info
67                .1
68                .and_then(|map| map.get(&info.0))
69                .cloned()
70                .unwrap_or_default(),
71        }
72    }
73}
74
75impl fmt::Display for DebugColumn {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        write!(
78            f,
79            "Column('{:?}', {} - {})",
80            self.column_type, self.index, self.annotation
81        )
82    }
83}
84
85/// A "virtual cell" is a PLONK cell that has been queried at a particular relative offset
86/// within a custom gate.
87#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
88pub struct VirtualCell {
89    name: String,
90    pub(super) column: Column,
91    pub(super) rotation: i32,
92}
93
94impl From<(Column, i32)> for VirtualCell {
95    fn from((column, rotation): (Column, i32)) -> Self {
96        VirtualCell {
97            name: "".to_string(),
98            column,
99            rotation,
100        }
101    }
102}
103
104impl<S: AsRef<str>> From<(S, Column, i32)> for VirtualCell {
105    fn from((name, column, rotation): (S, Column, i32)) -> Self {
106        VirtualCell {
107            name: name.as_ref().to_string(),
108            column,
109            rotation,
110        }
111    }
112}
113
114impl From<plonk::VirtualCell> for VirtualCell {
115    fn from(c: plonk::VirtualCell) -> Self {
116        VirtualCell {
117            name: "".to_string(),
118            column: c.column.into(),
119            rotation: c.rotation.0,
120        }
121    }
122}
123
124impl fmt::Display for VirtualCell {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        write!(f, "{}@{}", self.column, self.rotation)?;
127        if !self.name.is_empty() {
128            write!(f, "({})", self.name.as_str())?;
129        }
130        Ok(())
131    }
132}
133
134/// Helper structure used to be able to inject Column annotations inside a `Display` or `Debug` call.
135#[derive(Clone, Debug)]
136pub(super) struct DebugVirtualCell {
137    name: String,
138    column: DebugColumn,
139    rotation: i32,
140}
141
142impl From<(&VirtualCell, Option<&HashMap<Column, String>>)> for DebugVirtualCell {
143    fn from(info: (&VirtualCell, Option<&HashMap<Column, String>>)) -> Self {
144        DebugVirtualCell {
145            name: info.0.name.clone(),
146            column: DebugColumn::from((info.0.column, info.1)),
147            rotation: info.0.rotation,
148        }
149    }
150}
151
152impl fmt::Display for DebugVirtualCell {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(f, "{}@{}", self.column, self.rotation)?;
155        if !self.name.is_empty() {
156            write!(f, "({})", self.name)?;
157        }
158        Ok(())
159    }
160}
161
162/// Metadata about a configured gate within a circuit.
163#[derive(Debug, PartialEq, Eq, Clone)]
164pub struct Gate {
165    /// The index of the active gate. These indices are assigned in the order in which
166    /// `ConstraintSystem::create_gate` is called during `Circuit::configure`.
167    pub(super) index: usize,
168    /// The name of the active gate. These are specified by the gate creator (such as
169    /// a chip implementation), and is not enforced to be unique.
170    pub(super) name: String,
171}
172
173impl fmt::Display for Gate {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        write!(f, "Gate {} ('{}')", self.index, self.name.as_str())
176    }
177}
178
179impl<S: AsRef<str>> From<(usize, S)> for Gate {
180    fn from((index, name): (usize, S)) -> Self {
181        Gate {
182            index,
183            name: name.as_ref().to_string(),
184        }
185    }
186}
187
188/// Metadata about a configured constraint within a circuit.
189#[derive(Debug, PartialEq, Eq, Clone)]
190pub struct Constraint {
191    /// The gate containing the constraint.
192    pub(super) gate: Gate,
193    /// The index of the polynomial constraint within the gate. These indices correspond
194    /// to the order in which the constraints are returned from the closure passed to
195    /// `ConstraintSystem::create_gate` during `Circuit::configure`.
196    pub(super) index: usize,
197    /// The name of the constraint. This is specified by the gate creator (such as a chip
198    /// implementation), and is not enforced to be unique.
199    pub(super) name: String,
200}
201
202impl fmt::Display for Constraint {
203    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204        write!(
205            f,
206            "Constraint {}{} in gate {} ('{}')",
207            self.index,
208            if self.name.is_empty() {
209                String::new()
210            } else {
211                format!(" ('{}')", self.name.as_str())
212            },
213            self.gate.index,
214            self.gate.name,
215        )
216    }
217}
218
219impl<S: AsRef<str>> From<(Gate, usize, S)> for Constraint {
220    fn from((gate, index, name): (Gate, usize, S)) -> Self {
221        Constraint {
222            gate,
223            index,
224            name: name.as_ref().to_string(),
225        }
226    }
227}
228
229/// Metadata about an assigned region within a circuit.
230#[derive(Clone)]
231pub struct Region {
232    /// The index of the region. These indices are assigned in the order in which
233    /// `Layouter::assign_region` is called during `Circuit::synthesize`.
234    pub(super) index: usize,
235    /// The name of the region. This is specified by the region creator (such as a chip
236    /// implementation), and is not enforced to be unique.
237    pub(super) name: String,
238    /// A reference to the annotations of the Columns that exist within this `Region`.
239    pub(super) column_annotations: Option<HashMap<ColumnMetadata, String>>,
240}
241
242impl Region {
243    /// Fetch the annotation of a `Column` within a `Region` providing it's associated metadata.
244    ///
245    /// This function will return `None` if:
246    /// - There's no annotation map generated for this `Region`.
247    /// - There's no entry on the annotation map corresponding to the metadata provided.
248    pub(crate) fn get_column_annotation(&self, metadata: ColumnMetadata) -> Option<String> {
249        self.column_annotations
250            .as_ref()
251            .and_then(|map| map.get(&metadata).cloned())
252    }
253}
254
255impl PartialEq for Region {
256    fn eq(&self, other: &Self) -> bool {
257        self.index == other.index && self.name == other.name
258    }
259}
260
261impl Eq for Region {}
262
263impl Debug for Region {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        write!(f, "Region {} ('{}')", self.index, self.name)
266    }
267}
268
269impl fmt::Display for Region {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        write!(f, "Region {} ('{}')", self.index, self.name.as_str())
272    }
273}
274
275impl From<(usize, String)> for Region {
276    fn from((index, name): (usize, String)) -> Self {
277        Region {
278            index,
279            name,
280            column_annotations: None,
281        }
282    }
283}
284
285impl From<(usize, &str)> for Region {
286    fn from((index, name): (usize, &str)) -> Self {
287        Region {
288            index,
289            name: name.to_owned(),
290            column_annotations: None,
291        }
292    }
293}
294
295impl From<(usize, String, HashMap<ColumnMetadata, String>)> for Region {
296    fn from((index, name, annotations): (usize, String, HashMap<ColumnMetadata, String>)) -> Self {
297        Region {
298            index,
299            name,
300            column_annotations: Some(annotations),
301        }
302    }
303}
304
305impl From<(usize, &str, HashMap<ColumnMetadata, String>)> for Region {
306    fn from((index, name, annotations): (usize, &str, HashMap<ColumnMetadata, String>)) -> Self {
307        Region {
308            index,
309            name: name.to_owned(),
310            column_annotations: Some(annotations),
311        }
312    }
313}