1use std::{convert::TryInto, fmt, marker::PhantomData};
4
5use ff::Field;
6
7use crate::{
8 arithmetic::FieldExt,
9 plonk::{Advice, Any, Assigned, Column, Error, Fixed, Instance, Selector, TableColumn},
10};
11
12pub mod floor_planner;
13pub use floor_planner::single_pass::SimpleFloorPlanner;
14
15pub mod layouter;
16
17pub trait Chip<F: FieldExt>: Sized {
26 type Config: fmt::Debug + Clone;
31
32 type Loaded: fmt::Debug + Clone;
37
38 fn config(&self) -> &Self::Config;
40
41 fn loaded(&self) -> &Self::Loaded;
46}
47
48#[derive(Clone, Copy, Debug)]
50pub struct RegionIndex(usize);
51
52impl From<usize> for RegionIndex {
53 fn from(idx: usize) -> RegionIndex {
54 RegionIndex(idx)
55 }
56}
57
58impl std::ops::Deref for RegionIndex {
59 type Target = usize;
60
61 fn deref(&self) -> &Self::Target {
62 &self.0
63 }
64}
65
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68pub struct RegionStart(usize);
69
70impl From<usize> for RegionStart {
71 fn from(idx: usize) -> RegionStart {
72 RegionStart(idx)
73 }
74}
75
76impl std::ops::Deref for RegionStart {
77 type Target = usize;
78
79 fn deref(&self) -> &Self::Target {
80 &self.0
81 }
82}
83
84#[derive(Clone, Copy, Debug)]
86pub struct Cell {
87 region_index: RegionIndex,
89 row_offset: usize,
91 column: Column<Any>,
93}
94
95#[derive(Clone, Debug)]
97pub struct AssignedCell<V, F: Field> {
98 value: Option<V>,
99 cell: Cell,
100 _marker: PhantomData<F>,
101}
102
103impl<V, F: Field> AssignedCell<V, F> {
104 pub fn value(&self) -> Option<&V> {
106 self.value.as_ref()
107 }
108
109 pub fn cell(&self) -> Cell {
111 self.cell
112 }
113}
114
115impl<V, F: Field> AssignedCell<V, F>
116where
117 for<'v> Assigned<F>: From<&'v V>,
118{
119 pub fn value_field(&self) -> Option<Assigned<F>> {
121 self.value().map(|v| v.into())
122 }
123}
124
125impl<F: Field> AssignedCell<Assigned<F>, F> {
126 pub fn evaluate(self) -> AssignedCell<F, F> {
131 AssignedCell {
132 value: self.value.map(|v| v.evaluate()),
133 cell: self.cell,
134 _marker: Default::default(),
135 }
136 }
137}
138
139impl<V: Clone, F: Field> AssignedCell<V, F>
140where
141 for<'v> Assigned<F>: From<&'v V>,
142{
143 pub fn copy_advice<A, AR>(
148 &self,
149 annotation: A,
150 region: &mut Region<'_, F>,
151 column: Column<Advice>,
152 offset: usize,
153 ) -> Result<Self, Error>
154 where
155 A: Fn() -> AR,
156 AR: Into<String>,
157 {
158 let assigned_cell = region.assign_advice(annotation, column, offset, || {
159 self.value.clone().ok_or(Error::Synthesis)
160 })?;
161 region.constrain_equal(assigned_cell.cell(), self.cell())?;
162
163 Ok(assigned_cell)
164 }
165}
166
167#[derive(Debug)]
179pub struct Region<'r, F: Field> {
180 region: &'r mut dyn layouter::RegionLayouter<F>,
181}
182
183impl<'r, F: Field> From<&'r mut dyn layouter::RegionLayouter<F>> for Region<'r, F> {
184 fn from(region: &'r mut dyn layouter::RegionLayouter<F>) -> Self {
185 Region { region }
186 }
187}
188
189impl<'r, F: Field> Region<'r, F> {
190 pub(crate) fn enable_selector<A, AR>(
192 &mut self,
193 annotation: A,
194 selector: &Selector,
195 offset: usize,
196 ) -> Result<(), Error>
197 where
198 A: Fn() -> AR,
199 AR: Into<String>,
200 {
201 self.region
202 .enable_selector(&|| annotation().into(), selector, offset)
203 }
204
205 pub fn assign_advice<'v, V, VR, A, AR>(
209 &'v mut self,
210 annotation: A,
211 column: Column<Advice>,
212 offset: usize,
213 mut to: V,
214 ) -> Result<AssignedCell<VR, F>, Error>
215 where
216 V: FnMut() -> Result<VR, Error> + 'v,
217 for<'vr> Assigned<F>: From<&'vr VR>,
218 A: Fn() -> AR,
219 AR: Into<String>,
220 {
221 let mut value = None;
222 let cell =
223 self.region
224 .assign_advice(&|| annotation().into(), column, offset, &mut || {
225 let v = to()?;
226 let value_f = (&v).into();
227 value = Some(v);
228 Ok(value_f)
229 })?;
230
231 Ok(AssignedCell {
232 value,
233 cell,
234 _marker: PhantomData,
235 })
236 }
237
238 pub fn assign_advice_from_constant<VR, A, AR>(
245 &mut self,
246 annotation: A,
247 column: Column<Advice>,
248 offset: usize,
249 constant: VR,
250 ) -> Result<AssignedCell<VR, F>, Error>
251 where
252 for<'vr> Assigned<F>: From<&'vr VR>,
253 A: Fn() -> AR,
254 AR: Into<String>,
255 {
256 let cell = self.region.assign_advice_from_constant(
257 &|| annotation().into(),
258 column,
259 offset,
260 (&constant).into(),
261 )?;
262
263 Ok(AssignedCell {
264 value: Some(constant),
265 cell,
266 _marker: PhantomData,
267 })
268 }
269
270 pub fn assign_advice_from_instance<A, AR>(
275 &mut self,
276 annotation: A,
277 instance: Column<Instance>,
278 row: usize,
279 advice: Column<Advice>,
280 offset: usize,
281 ) -> Result<AssignedCell<F, F>, Error>
282 where
283 A: Fn() -> AR,
284 AR: Into<String>,
285 {
286 let (cell, value) = self.region.assign_advice_from_instance(
287 &|| annotation().into(),
288 instance,
289 row,
290 advice,
291 offset,
292 )?;
293
294 Ok(AssignedCell {
295 value,
296 cell,
297 _marker: PhantomData,
298 })
299 }
300
301 pub fn assign_fixed<'v, V, VR, A, AR>(
305 &'v mut self,
306 annotation: A,
307 column: Column<Fixed>,
308 offset: usize,
309 mut to: V,
310 ) -> Result<AssignedCell<VR, F>, Error>
311 where
312 V: FnMut() -> Result<VR, Error> + 'v,
313 for<'vr> Assigned<F>: From<&'vr VR>,
314 A: Fn() -> AR,
315 AR: Into<String>,
316 {
317 let mut value = None;
318 let cell =
319 self.region
320 .assign_fixed(&|| annotation().into(), column, offset, &mut || {
321 let v = to()?;
322 let value_f = (&v).into();
323 value = Some(v);
324 Ok(value_f)
325 })?;
326
327 Ok(AssignedCell {
328 value,
329 cell,
330 _marker: PhantomData,
331 })
332 }
333
334 pub fn constrain_constant<VR>(&mut self, cell: Cell, constant: VR) -> Result<(), Error>
338 where
339 VR: Into<Assigned<F>>,
340 {
341 self.region.constrain_constant(cell, constant.into())
342 }
343
344 pub fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
349 self.region.constrain_equal(left, right)
350 }
351}
352
353#[derive(Debug)]
355pub struct Table<'r, F: Field> {
356 table: &'r mut dyn layouter::TableLayouter<F>,
357}
358
359impl<'r, F: Field> From<&'r mut dyn layouter::TableLayouter<F>> for Table<'r, F> {
360 fn from(table: &'r mut dyn layouter::TableLayouter<F>) -> Self {
361 Table { table }
362 }
363}
364
365impl<'r, F: Field> Table<'r, F> {
366 pub fn assign_cell<'v, V, VR, A, AR>(
372 &'v mut self,
373 annotation: A,
374 column: TableColumn,
375 offset: usize,
376 mut to: V,
377 ) -> Result<(), Error>
378 where
379 V: FnMut() -> Result<VR, Error> + 'v,
380 VR: Into<Assigned<F>>,
381 A: Fn() -> AR,
382 AR: Into<String>,
383 {
384 self.table
385 .assign_cell(&|| annotation().into(), column, offset, &mut || {
386 to().map(|v| v.into())
387 })
388 }
389}
390
391pub trait Layouter<F: Field> {
397 type Root: Layouter<F>;
400
401 fn assign_region<A, AR, N, NR>(&mut self, name: N, assignment: A) -> Result<AR, Error>
414 where
415 A: FnMut(Region<'_, F>) -> Result<AR, Error>,
416 N: Fn() -> NR,
417 NR: Into<String>;
418
419 fn assign_table<A, N, NR>(&mut self, name: N, assignment: A) -> Result<(), Error>
428 where
429 A: FnMut(Table<'_, F>) -> Result<(), Error>,
430 N: Fn() -> NR,
431 NR: Into<String>;
432
433 fn constrain_instance(
436 &mut self,
437 cell: Cell,
438 column: Column<Instance>,
439 row: usize,
440 ) -> Result<(), Error>;
441
442 fn get_root(&mut self) -> &mut Self::Root;
446
447 fn push_namespace<NR, N>(&mut self, name_fn: N)
451 where
452 NR: Into<String>,
453 N: FnOnce() -> NR;
454
455 fn pop_namespace(&mut self, gadget_name: Option<String>);
459
460 fn namespace<NR, N>(&mut self, name_fn: N) -> NamespacedLayouter<'_, F, Self::Root>
462 where
463 NR: Into<String>,
464 N: FnOnce() -> NR,
465 {
466 self.get_root().push_namespace(name_fn);
467
468 NamespacedLayouter(self.get_root(), PhantomData)
469 }
470}
471
472#[derive(Debug)]
475pub struct NamespacedLayouter<'a, F: Field, L: Layouter<F> + 'a>(&'a mut L, PhantomData<F>);
476
477impl<'a, F: Field, L: Layouter<F> + 'a> Layouter<F> for NamespacedLayouter<'a, F, L> {
478 type Root = L::Root;
479
480 fn assign_region<A, AR, N, NR>(&mut self, name: N, assignment: A) -> Result<AR, Error>
481 where
482 A: FnMut(Region<'_, F>) -> Result<AR, Error>,
483 N: Fn() -> NR,
484 NR: Into<String>,
485 {
486 self.0.assign_region(name, assignment)
487 }
488
489 fn assign_table<A, N, NR>(&mut self, name: N, assignment: A) -> Result<(), Error>
490 where
491 A: FnMut(Table<'_, F>) -> Result<(), Error>,
492 N: Fn() -> NR,
493 NR: Into<String>,
494 {
495 self.0.assign_table(name, assignment)
496 }
497
498 fn constrain_instance(
499 &mut self,
500 cell: Cell,
501 column: Column<Instance>,
502 row: usize,
503 ) -> Result<(), Error> {
504 self.0.constrain_instance(cell, column, row)
505 }
506
507 fn get_root(&mut self) -> &mut Self::Root {
508 self.0.get_root()
509 }
510
511 fn push_namespace<NR, N>(&mut self, _name_fn: N)
512 where
513 NR: Into<String>,
514 N: FnOnce() -> NR,
515 {
516 panic!("Only the root's push_namespace should be called");
517 }
518
519 fn pop_namespace(&mut self, _gadget_name: Option<String>) {
520 panic!("Only the root's pop_namespace should be called");
521 }
522}
523
524impl<'a, F: Field, L: Layouter<F> + 'a> Drop for NamespacedLayouter<'a, F, L> {
525 fn drop(&mut self) {
526 let gadget_name = {
527 #[cfg(feature = "gadget-traces")]
528 {
529 let mut gadget_name = None;
530 let mut is_second_frame = false;
531 backtrace::trace(|frame| {
532 if is_second_frame {
533 backtrace::resolve_frame(frame, |symbol| {
535 gadget_name = symbol.name().map(|name| format!("{:#}", name));
536 });
537
538 false
540 } else {
541 is_second_frame = true;
543 true
544 }
545 });
546 gadget_name
547 }
548
549 #[cfg(not(feature = "gadget-traces"))]
550 None
551 };
552
553 self.get_root().pop_namespace(gadget_name);
554 }
555}