Only keep config() and loaded() generic on Chip trait

Co-authored-by: Jack Grigg <jack@electriccoin.co>
This commit is contained in:
therealyingtong 2021-04-22 06:58:44 +08:00
parent 40e7bec352
commit 3ad1c43fb8
4 changed files with 152 additions and 245 deletions

View File

@ -1,7 +1,5 @@
extern crate halo2;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::marker::PhantomData;
use halo2::{
@ -9,33 +7,37 @@ use halo2::{
circuit::{layouter::SingleChipLayouter, Cell, Chip, Config, Layouter, Region},
dev::VerifyFailure,
plonk::{
Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Error, Permutation, Selector,
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
Selector,
},
poly::Rotation,
};
/// A variable representing a number.
#[derive(Clone)]
struct Number<F: FieldExt> {
cell: Cell,
value: Option<F>,
}
// ANCHOR: instructions
trait NumericInstructions<F: FieldExt>: Chip<F> {
/// Variable representing a number.
type Num;
/// Loads a number into the circuit as a private input.
fn load_private(
&self,
layouter: &mut impl Layouter<F>,
a: Option<F>,
) -> Result<Self::Num, Error>;
fn load_private(&self, layouter: impl Layouter<F>, a: Option<F>) -> Result<Self::Num, Error>;
/// Returns `c = a * b`.
fn mul(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error>;
/// Exposes a number as a public input to the circuit.
fn expose_public(&self, layouter: &mut impl Layouter<F>, num: Self::Num) -> Result<(), Error>;
fn expose_public(&self, layouter: impl Layouter<F>, num: Self::Num) -> Result<(), Error>;
}
// ANCHOR_END: instructions
@ -87,19 +89,31 @@ impl Config for FieldConfigEnum {
// ANCHOR_END: chip-config
// ANCHOR: chip-impl
// ANCHOR: chip-trait-impl
impl<F: FieldExt> Chip<F> for FieldChip<F> {
type Config = FieldConfigEnum;
type Loaded = ();
fn config(&self) -> &Self::Config {
&self.config
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR_END: chip-trait-impl
// ANCHOR: chip-impl
impl<F: FieldExt> FieldChip<F> {
fn new() -> Self {
Self {
config: Self::Config::empty(),
config: <Self as Chip<F>>::Config::empty(),
_marker: PhantomData,
}
}
fn construct(config: Self::Config, _loaded: Self::Loaded) -> Self {
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
Self {
config,
_marker: PhantomData,
@ -109,16 +123,9 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
fn configure(
&mut self,
meta: &mut ConstraintSystem<F>,
_selectors: BTreeMap<&str, Selector>,
columns: BTreeMap<&str, Column<Any>>,
_perms: BTreeMap<&str, Permutation>,
) -> Self::Config {
let advice = [
*columns.get("advice0").unwrap(),
*columns.get("advice1").unwrap(),
];
let instance = *columns.get("instance").unwrap();
advice: [Column<Advice>; 2],
instance: Column<Instance>,
) -> <Self as Chip<F>>::Config {
let perm = Permutation::new(
meta,
&advice
@ -143,9 +150,9 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
// offset adds a cost to the proof. The most common offsets are 0 (the
// current row), 1 (the next row), and -1 (the previous row), for which
// `Rotation` has specific constructors.
let lhs = meta.query_any(advice[0], Rotation::cur());
let rhs = meta.query_any(advice[1], Rotation::cur());
let out = meta.query_any(advice[0], Rotation::next());
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_mul = meta.query_selector(s_mul, Rotation::cur());
// The polynomial expression returned from `create_gate` will be
@ -160,8 +167,8 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
meta.create_gate("public input", |meta| {
// We choose somewhat-arbitrarily that we will use the second advice
// column for exposing numbers as public inputs.
let a = meta.query_any(advice[1], Rotation::cur());
let p = meta.query_any(instance, Rotation::cur());
let a = meta.query_advice(advice[1], Rotation::cur());
let p = meta.query_instance(instance, Rotation::cur());
let s = meta.query_selector(s_pub, Rotation::cur());
// We simply constrain the advice cell to be equal to the instance cell,
@ -170,46 +177,23 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
});
FieldConfigEnum::Config(FieldConfig {
advice: [
Column::<Advice>::try_from(advice[0]).unwrap(),
Column::<Advice>::try_from(advice[1]).unwrap(),
],
perm: perm,
s_mul: s_mul,
s_pub: s_pub,
advice,
perm,
s_mul,
s_pub,
})
}
fn config(&self) -> &Self::Config {
&self.config
}
fn load(&mut self, _layouter: &mut impl Layouter<F>) -> Result<(), halo2::plonk::Error> {
// None of the instructions implemented by this chip have any fixed state.
// But if we required e.g. a lookup table, this is where we would load it.
Ok(())
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR_END: chip-impl
// ANCHOR: instructions-impl
/// A variable representing a number.
#[derive(Clone)]
struct Number<F: FieldExt> {
cell: Cell,
value: Option<F>,
}
impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
type Num = Number<F>;
fn load_private(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
value: Option<F>,
) -> Result<Self::Num, Error> {
let config = match self.config() {
@ -236,7 +220,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
fn mul(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error> {
@ -292,7 +276,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
Ok(out.unwrap())
}
fn expose_public(&self, layouter: &mut impl Layouter<F>, num: Self::Num) -> Result<(), Error> {
fn expose_public(&self, mut layouter: impl Layouter<F>, num: Self::Num) -> Result<(), Error> {
let config = match self.config() {
FieldConfigEnum::Config(config) => config.clone(),
_ => unreachable!(),
@ -339,16 +323,14 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
// We create the two advice columns that FieldChip uses for I/O.
// We also need an instance column to store public inputs.
let advice = [meta.advice_column(), meta.advice_column()];
let mut columns: BTreeMap<&str, Column<Any>> = BTreeMap::new();
columns.insert("advice0", meta.advice_column().into());
columns.insert("advice1", meta.advice_column().into());
columns.insert("instance", meta.instance_column().into());
// We also need an instance column to store public inputs.
let instance = meta.instance_column();
let mut field_chip = FieldChip::new();
field_chip.configure(meta, BTreeMap::default(), columns, BTreeMap::default())
field_chip.configure(meta, advice, instance)
}
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
@ -356,8 +338,8 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
let field_chip = FieldChip::<F>::construct(config, ());
// Load our private values into the circuit.
let a = field_chip.load_private(&mut layouter, self.a)?;
let b = field_chip.load_private(&mut layouter, self.b)?;
let a = field_chip.load_private(layouter.namespace(|| "load a"), self.a)?;
let b = field_chip.load_private(layouter.namespace(|| "load b"), self.b)?;
// We only have access to plain multiplication.
// We could implement our circuit as:
@ -368,11 +350,11 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
// but it's more efficient to implement it as:
// ab = a*b
// c = ab^2
let ab = field_chip.mul(&mut layouter, a, b)?;
let c = field_chip.mul(&mut layouter, ab.clone(), ab)?;
let ab = field_chip.mul(layouter.namespace(|| "a * b"), a, b)?;
let c = field_chip.mul(layouter.namespace(|| "ab * ab"), ab.clone(), ab)?;
// Expose the result as a public input to the circuit.
field_chip.expose_public(&mut layouter, c)
field_chip.expose_public(layouter.namespace(|| "expose c"), c)
}
}
// ANCHOR_END: circuit

View File

@ -1,7 +1,5 @@
extern crate halo2;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::marker::PhantomData;
use halo2::{
@ -9,7 +7,8 @@ use halo2::{
circuit::{layouter::SingleChipLayouter, Cell, Chip, Config, Layouter, Region},
dev::VerifyFailure,
plonk::{
Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Error, Permutation, Selector,
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
Selector,
},
poly::Rotation,
};
@ -29,7 +28,7 @@ trait FieldInstructions<F: FieldExt>: AddInstructions<F> + MulInstructions<F> {
/// Loads a number into the circuit as a private input.
fn load_private(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Option<F>,
) -> Result<<Self as FieldInstructions<F>>::Num, Error>;
@ -45,7 +44,7 @@ trait FieldInstructions<F: FieldExt>: AddInstructions<F> + MulInstructions<F> {
/// Exposes a number as a public input to the circuit.
fn expose_public(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
num: <Self as FieldInstructions<F>>::Num,
) -> Result<(), Error>;
}
@ -59,7 +58,7 @@ trait AddInstructions<F: FieldExt>: Chip<F> {
/// Returns `c = a + b`.
fn add(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error>;
@ -74,7 +73,7 @@ trait MulInstructions<F: FieldExt>: Chip<F> {
/// Returns `c = a * b`.
fn mul(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error>;
@ -180,19 +179,31 @@ struct MulChip<F: FieldExt> {
}
// ANCHOR_END: mul-chip
// ANCHOR: add-chip-impl
// ANCHOR: add-chip-trait-impl
impl<F: FieldExt> Chip<F> for AddChip<F> {
type Config = AddConfigEnum;
type Loaded = ();
fn config(&self) -> &Self::Config {
&self.config
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR END: add-chip-trait-impl
// ANCHOR: add-chip-impl
impl<F: FieldExt> AddChip<F> {
fn new() -> Self {
Self {
config: Self::Config::empty(),
config: <Self as Chip<F>>::Config::empty(),
_marker: PhantomData,
}
}
fn construct(config: Self::Config, _loaded: Self::Loaded) -> Self {
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
Self {
config,
_marker: PhantomData,
@ -202,51 +213,28 @@ impl<F: FieldExt> Chip<F> for AddChip<F> {
fn configure(
&mut self,
meta: &mut ConstraintSystem<F>,
_selectors: BTreeMap<&str, Selector>,
columns: BTreeMap<&str, Column<Any>>,
perms: BTreeMap<&str, Permutation>,
) -> Self::Config {
let advice = [
*columns.get("advice0").unwrap(),
*columns.get("advice1").unwrap(),
];
let perm = perms.get("perm").unwrap();
advice: [Column<Advice>; 2],
perm: Permutation,
) -> <Self as Chip<F>>::Config {
let s_add = meta.selector();
// Define our addition gate!
meta.create_gate("add", |meta| {
let lhs = meta.query_any(advice[0], Rotation::cur());
let rhs = meta.query_any(advice[1], Rotation::cur());
let out = meta.query_any(advice[0], Rotation::next());
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_add = meta.query_selector(s_add, Rotation::cur());
s_add * (lhs + rhs + out * -F::one())
});
let config = AddConfigEnum::Config(AddConfig {
advice: [
Column::<Advice>::try_from(advice[0]).unwrap(),
Column::<Advice>::try_from(advice[1]).unwrap(),
],
perm: perm.clone(),
advice,
perm,
s_add,
});
self.config = config.clone();
config
}
fn config(&self) -> &Self::Config {
&self.config
}
fn load(&mut self, _layouter: &mut impl Layouter<F>) -> Result<(), halo2::plonk::Error> {
// None of the instructions implemented by this chip have any fixed state.
// But if we required e.g. a lookup table, this is where we would load it.
Ok(())
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR END: add-chip-impl
@ -255,7 +243,7 @@ impl<F: FieldExt> AddInstructions<F> for FieldChip<F> {
type Num = Number<F>;
fn add(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error> {
@ -273,7 +261,7 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
fn add(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error> {
@ -331,19 +319,31 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
}
// ANCHOR END: add-instructions-impl
// ANCHOR: mul-chip-impl
// ANCHOR: mul-chip-trait-impl
impl<F: FieldExt> Chip<F> for MulChip<F> {
type Config = MulConfigEnum;
type Loaded = ();
fn config(&self) -> &Self::Config {
&self.config
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR END: mul-chip-trait-impl
// ANCHOR: mul-chip-impl
impl<F: FieldExt> MulChip<F> {
fn new() -> Self {
Self {
config: Self::Config::empty(),
config: <Self as Chip<F>>::Config::empty(),
_marker: PhantomData,
}
}
fn construct(config: Self::Config, _loaded: Self::Loaded) -> Self {
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
Self {
config,
_marker: PhantomData,
@ -353,15 +353,9 @@ impl<F: FieldExt> Chip<F> for MulChip<F> {
fn configure(
&mut self,
meta: &mut ConstraintSystem<F>,
_selectors: BTreeMap<&str, Selector>,
columns: BTreeMap<&str, Column<Any>>,
perms: BTreeMap<&str, Permutation>,
) -> Self::Config {
let advice = [
*columns.get("advice0").unwrap(),
*columns.get("advice1").unwrap(),
];
let perm = perms.get("perm").unwrap();
advice: [Column<Advice>; 2],
perm: Permutation,
) -> <Self as Chip<F>>::Config {
let s_mul = meta.selector();
// Define our multiplication gate!
@ -378,9 +372,9 @@ impl<F: FieldExt> Chip<F> for MulChip<F> {
// offset adds a cost to the proof. The most common offsets are 0 (the
// current row), 1 (the next row), and -1 (the previous row), for which
// `Rotation` has specific constructors.
let lhs = meta.query_any(advice[0], Rotation::cur());
let rhs = meta.query_any(advice[1], Rotation::cur());
let out = meta.query_any(advice[0], Rotation::next());
let lhs = meta.query_advice(advice[0], Rotation::cur());
let rhs = meta.query_advice(advice[1], Rotation::cur());
let out = meta.query_advice(advice[0], Rotation::next());
let s_mul = meta.query_selector(s_mul, Rotation::cur());
// The polynomial expression returned from `create_gate` will be
@ -392,39 +386,22 @@ impl<F: FieldExt> Chip<F> for MulChip<F> {
});
let config = MulConfigEnum::Config(MulConfig {
advice: [
Column::<Advice>::try_from(advice[0]).unwrap(),
Column::<Advice>::try_from(advice[1]).unwrap(),
],
perm: perm.clone(),
advice,
perm,
s_mul,
});
self.config = config.clone();
config
}
fn config(&self) -> &Self::Config {
&self.config
}
fn load(&mut self, _layouter: &mut impl Layouter<F>) -> Result<(), halo2::plonk::Error> {
// None of the instructions implemented by this chip have any fixed state.
// But if we required e.g. a lookup table, this is where we would load it.
Ok(())
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR END: mul-chip-impl
// ANCHOR_END: mul-chip-impl
// ANCHOR: mul-instructions-impl
impl<F: FieldExt> MulInstructions<F> for FieldChip<F> {
type Num = Number<F>;
fn mul(
&self,
layouter: &mut impl Layouter<F>,
layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error> {
@ -442,7 +419,7 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
fn mul(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
a: Self::Num,
b: Self::Num,
) -> Result<Self::Num, Error> {
@ -500,19 +477,31 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
}
// ANCHOR END: mul-instructions-impl
// ANCHOR: field-chip-impl
// ANCHOR: field-chip-trait-impl
impl<F: FieldExt> Chip<F> for FieldChip<F> {
type Config = FieldConfigEnum;
type Loaded = ();
fn config(&self) -> &Self::Config {
&self.config
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR_END: field-chip-trait-impl
// ANCHOR: field-chip-impl
impl<F: FieldExt> FieldChip<F> {
fn new() -> Self {
Self {
config: Self::Config::empty(),
config: <Self as Chip<F>>::Config::empty(),
_marker: PhantomData,
}
}
fn construct(config: Self::Config, _loaded: Self::Loaded) -> Self {
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
Self {
config,
_marker: PhantomData,
@ -522,16 +511,9 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
fn configure(
&mut self,
meta: &mut ConstraintSystem<F>,
_selectors: BTreeMap<&str, Selector>,
columns: BTreeMap<&str, Column<Any>>,
_perms: BTreeMap<&str, Permutation>,
) -> Self::Config {
let advice = [
*columns.get("advice0").unwrap(),
*columns.get("advice1").unwrap(),
];
let instance = *columns.get("instance").unwrap();
advice: [Column<Advice>; 2],
instance: Column<Instance>,
) -> <Self as Chip<F>>::Config {
let perm = Permutation::new(
meta,
&advice
@ -545,8 +527,8 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
meta.create_gate("public input", |meta| {
// We choose somewhat-arbitrarily that we will use the second advice
// column for exposing numbers as public inputs.
let a = meta.query_any(advice[1], Rotation::cur());
let p = meta.query_any(instance, Rotation::cur());
let a = meta.query_advice(advice[1], Rotation::cur());
let p = meta.query_instance(instance, Rotation::cur());
let s = meta.query_selector(s_pub, Rotation::cur());
// We simply constrain the advice cell to be equal to the instance cell,
@ -554,43 +536,22 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
s * (p + a * -F::one())
});
let mut perms = BTreeMap::new();
perms.insert("perm", perm.clone());
let mut add_chip = AddChip::new();
let add_config =
add_chip.configure(meta, BTreeMap::default(), columns.clone(), perms.clone());
let add_config = add_chip.configure(meta, advice.clone(), perm.clone());
let mut mul_chip = MulChip::new();
let mul_config = mul_chip.configure(meta, BTreeMap::default(), columns, perms);
let mul_config = mul_chip.configure(meta, advice.clone(), perm.clone());
let config = FieldConfigEnum::Config(FieldConfig {
advice: [
Column::<Advice>::try_from(advice[0]).unwrap(),
Column::<Advice>::try_from(advice[1]).unwrap(),
],
perm: perm,
s_pub: s_pub,
add_config: add_config,
mul_config: mul_config,
advice,
perm,
s_pub,
add_config,
mul_config,
});
self.config = config.clone();
config
}
fn config(&self) -> &Self::Config {
&self.config
}
fn load(&mut self, _layouter: &mut impl Layouter<F>) -> Result<(), halo2::plonk::Error> {
// None of the instructions implemented by this chip have any fixed state.
// But if we required e.g. a lookup table, this is where we would load it.
Ok(())
}
fn loaded(&self) -> &Self::Loaded {
&()
}
}
// ANCHOR_END: field-chip-impl
@ -600,7 +561,7 @@ impl<F: FieldExt> FieldInstructions<F> for FieldChip<F> {
fn load_private(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
value: Option<F>,
) -> Result<<Self as FieldInstructions<F>>::Num, Error> {
let config = match self.config() {
@ -633,21 +594,13 @@ impl<F: FieldExt> FieldInstructions<F> for FieldChip<F> {
b: <Self as FieldInstructions<F>>::Num,
c: <Self as FieldInstructions<F>>::Num,
) -> Result<<Self as FieldInstructions<F>>::Num, Error> {
let config = match self.config() {
FieldConfigEnum::Config(config) => config,
_ => unreachable!(),
};
let add_chip = AddChip::<F>::construct(config.add_config.clone(), ());
let ab = add_chip.add(layouter, a, b)?;
let mul_chip = MulChip::<F>::construct(config.mul_config.clone(), ());
mul_chip.mul(layouter, ab, c)
let ab = self.add(layouter.namespace(|| "a + b"), a, b)?;
self.mul(layouter.namespace(|| "(a + b) * c"), ab, c)
}
fn expose_public(
&self,
layouter: &mut impl Layouter<F>,
mut layouter: impl Layouter<F>,
num: <Self as FieldInstructions<F>>::Num,
) -> Result<(), Error> {
let config = match self.config() {
@ -697,15 +650,13 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
// We create the two advice columns that FieldChip uses for I/O.
// We also need an instance column to store public inputs.
let advice = [meta.advice_column(), meta.advice_column()];
let mut columns: BTreeMap<&str, Column<Any>> = BTreeMap::new();
columns.insert("advice0", meta.advice_column().into());
columns.insert("advice1", meta.advice_column().into());
columns.insert("instance", meta.instance_column().into());
// We also need an instance column to store public inputs.
let instance = meta.instance_column();
let mut field_chip = FieldChip::new();
field_chip.configure(meta, BTreeMap::default(), columns, BTreeMap::default())
field_chip.configure(meta, advice, instance)
}
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
@ -713,15 +664,15 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
let field_chip = FieldChip::<F>::construct(config, ());
// Load our private values into the circuit.
let a = field_chip.load_private(&mut layouter, self.a)?;
let b = field_chip.load_private(&mut layouter, self.b)?;
let c = field_chip.load_private(&mut layouter, self.c)?;
let a = field_chip.load_private(layouter.namespace(|| "load a"), self.a)?;
let b = field_chip.load_private(layouter.namespace(|| "load b"), self.b)?;
let c = field_chip.load_private(layouter.namespace(|| "load c"), self.c)?;
// Use `add_and_mul` to get `d = (a + b) * c`.
let d = field_chip.add_and_mul(&mut layouter, a, b, c)?;
// Expose the result as a public input to the circuit.
field_chip.expose_public(&mut layouter, d)
field_chip.expose_public(layouter.namespace(|| "expose d"), d)
}
}
// ANCHOR_END: circuit

View File

@ -1,10 +1,10 @@
//! Traits and structs for implementing circuit components.
use std::{collections::BTreeMap, fmt, marker::PhantomData};
use std::{fmt, marker::PhantomData};
use crate::{
arithmetic::FieldExt,
plonk::{Advice, Any, Column, ConstraintSystem, Error, Fixed, Permutation, Selector},
plonk::{Advice, Any, Column, Error, Fixed, Permutation},
};
pub mod layouter;
@ -46,39 +46,13 @@ pub trait Chip<F: FieldExt>: Sized {
/// [`Circuit::synthesize`]: crate::plonk::Circuit::synthesize
type Loaded: Loaded;
/// A new chip that is not yet configured or loaded.
fn new() -> Self;
/// A chip constructed from a given config and loaded state.
fn construct(config: Self::Config, loaded: Self::Loaded) -> Self;
/// The chip is responsible for mutating the constraint system to set up
/// the columns, gates, lookups and permutations it needs.
///
/// We allow for the chip to use pre-existing columns, selectors, and
/// permutations in its configuration. Chips that are lower in a hierarchy
/// depend on other chips to pass down these objects.
fn configure(
&mut self,
meta: &mut ConstraintSystem<F>,
selectors: BTreeMap<&str, Selector>,
columns: BTreeMap<&str, Column<Any>>,
perms: BTreeMap<&str, Permutation>,
) -> Self::Config;
/// The chip holds its own configuration.
fn config(&self) -> &Self::Config;
/// Load any fixed configuration for this chip into the circuit, i.e.
/// assigns cells in fixed columns.
///
/// `self.loaded()` will panic if called inside this function.
fn load(&mut self, layouter: &mut impl Layouter<F>) -> Result<Self::Loaded, Error>;
/// Provides access to general chip state loaded at the beginning of circuit
/// synthesis.
///
/// Panics if called inside `Chip::load`.
/// Panics if called before `Chip::load`.
fn loaded(&self) -> &Self::Loaded;
}

View File

@ -74,7 +74,7 @@ pub struct SingleChipLayouter<'a, F: FieldExt, CS: Assignment<F> + 'a> {
regions: Vec<RegionStart>,
/// Stores the first empty row for each column.
columns: HashMap<Column<Any>, usize>,
marker: PhantomData<F>,
_marker: PhantomData<F>,
}
impl<'a, F: FieldExt, CS: Assignment<F> + 'a> fmt::Debug for SingleChipLayouter<'a, F, CS> {
@ -93,7 +93,7 @@ impl<'a, F: FieldExt, CS: Assignment<F>> SingleChipLayouter<'a, F, CS> {
cs,
regions: vec![],
columns: HashMap::default(),
marker: PhantomData,
_marker: PhantomData,
};
Ok(ret)
}