mirror of https://github.com/zcash/halo2.git
Remove empty() methods from Config and Loaded traits
Co-authored-by: Jack Grigg <jack@electriccoin.co>
This commit is contained in:
parent
7524c95547
commit
21aaab20f6
|
@ -4,7 +4,7 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
use halo2::{
|
use halo2::{
|
||||||
arithmetic::FieldExt,
|
arithmetic::FieldExt,
|
||||||
circuit::{layouter::SingleChipLayouter, Cell, Chip, Config, Layouter, Region},
|
circuit::{layouter::SingleChipLayouter, Cell, Chip, Layouter, Region},
|
||||||
dev::VerifyFailure,
|
dev::VerifyFailure,
|
||||||
plonk::{
|
plonk::{
|
||||||
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
|
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
|
||||||
|
@ -13,13 +13,6 @@ use halo2::{
|
||||||
poly::Rotation,
|
poly::Rotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A variable representing a number.
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Number<F: FieldExt> {
|
|
||||||
cell: Cell,
|
|
||||||
value: Option<F>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ANCHOR: instructions
|
// ANCHOR: instructions
|
||||||
trait NumericInstructions<F: FieldExt>: Chip<F> {
|
trait NumericInstructions<F: FieldExt>: Chip<F> {
|
||||||
/// Variable representing a number.
|
/// Variable representing a number.
|
||||||
|
@ -45,75 +38,14 @@ trait NumericInstructions<F: FieldExt>: Chip<F> {
|
||||||
/// The chip that will implement our instructions! Chips store their own
|
/// The chip that will implement our instructions! Chips store their own
|
||||||
/// config, as well as type markers if necessary.
|
/// config, as well as type markers if necessary.
|
||||||
struct FieldChip<F: FieldExt> {
|
struct FieldChip<F: FieldExt> {
|
||||||
config: FieldConfigEnum,
|
config: FieldConfig,
|
||||||
_marker: PhantomData<F>,
|
_marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
// ANCHOR_END: chip
|
// ANCHOR_END: chip
|
||||||
|
|
||||||
// ANCHOR: chip-config
|
|
||||||
/// Chip state is stored in a config struct. This is generated by the chip
|
|
||||||
/// during configuration, and then stored inside the chip.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct FieldConfig {
|
|
||||||
/// For this chip, we will use two advice columns to implement our instructions.
|
|
||||||
/// These are also the columns through which we communicate with other parts of
|
|
||||||
/// the circuit.
|
|
||||||
advice: [Column<Advice>; 2],
|
|
||||||
|
|
||||||
// We need to create a permutation between our advice columns. This allows us to
|
|
||||||
// copy numbers within these columns from arbitrary rows, which we can use to load
|
|
||||||
// inputs into our instruction regions.
|
|
||||||
perm: Permutation,
|
|
||||||
|
|
||||||
// We need a selector to enable the multiplication gate, so that we aren't placing
|
|
||||||
// any constraints on cells where `NumericInstructions::mul` is not being used.
|
|
||||||
// This is important when building larger circuits, where columns are used by
|
|
||||||
// multiple sets of instructions.
|
|
||||||
s_mul: Selector,
|
|
||||||
|
|
||||||
// The selector for the public-input gate, which uses one of the advice columns.
|
|
||||||
s_pub: Selector,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum FieldConfigEnum {
|
|
||||||
Empty,
|
|
||||||
Config(FieldConfig),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config for FieldConfigEnum {
|
|
||||||
fn empty() -> Self {
|
|
||||||
Self::Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ANCHOR_END: chip-config
|
|
||||||
|
|
||||||
// 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
|
// ANCHOR: chip-impl
|
||||||
impl<F: FieldExt> FieldChip<F> {
|
impl<F: FieldExt> FieldChip<F> {
|
||||||
fn new() -> Self {
|
fn construct(config: <Self as Chip<F>>::Config) -> Self {
|
||||||
Self {
|
|
||||||
config: <Self as Chip<F>>::Config::empty(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
|
@ -121,7 +53,6 @@ impl<F: FieldExt> FieldChip<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(
|
fn configure(
|
||||||
&mut self,
|
|
||||||
meta: &mut ConstraintSystem<F>,
|
meta: &mut ConstraintSystem<F>,
|
||||||
advice: [Column<Advice>; 2],
|
advice: [Column<Advice>; 2],
|
||||||
instance: Column<Instance>,
|
instance: Column<Instance>,
|
||||||
|
@ -176,17 +107,65 @@ impl<F: FieldExt> FieldChip<F> {
|
||||||
s * (p + a * -F::one())
|
s * (p + a * -F::one())
|
||||||
});
|
});
|
||||||
|
|
||||||
FieldConfigEnum::Config(FieldConfig {
|
FieldConfig {
|
||||||
advice,
|
advice,
|
||||||
perm,
|
perm,
|
||||||
s_mul,
|
s_mul,
|
||||||
s_pub,
|
s_pub,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ANCHOR: chip-trait-impl
|
||||||
|
impl<F: FieldExt> Chip<F> for FieldChip<F> {
|
||||||
|
type Config = FieldConfig;
|
||||||
|
type Loaded = ();
|
||||||
|
|
||||||
|
fn config(&self) -> &Self::Config {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
fn loaded(&self) -> &Self::Loaded {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ANCHOR_END: chip-trait-impl
|
||||||
|
|
||||||
// ANCHOR_END: chip-impl
|
// ANCHOR_END: chip-impl
|
||||||
|
|
||||||
|
// ANCHOR: chip-config
|
||||||
|
/// Chip state is stored in a config struct. This is generated by the chip
|
||||||
|
/// during configuration, and then stored inside the chip.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct FieldConfig {
|
||||||
|
/// For this chip, we will use two advice columns to implement our instructions.
|
||||||
|
/// These are also the columns through which we communicate with other parts of
|
||||||
|
/// the circuit.
|
||||||
|
advice: [Column<Advice>; 2],
|
||||||
|
|
||||||
|
// We need to create a permutation between our advice columns. This allows us to
|
||||||
|
// copy numbers within these columns from arbitrary rows, which we can use to load
|
||||||
|
// inputs into our instruction regions.
|
||||||
|
perm: Permutation,
|
||||||
|
|
||||||
|
// We need a selector to enable the multiplication gate, so that we aren't placing
|
||||||
|
// any constraints on cells where `NumericInstructions::mul` is not being used.
|
||||||
|
// This is important when building larger circuits, where columns are used by
|
||||||
|
// multiple sets of instructions.
|
||||||
|
s_mul: Selector,
|
||||||
|
|
||||||
|
// The selector for the public-input gate, which uses one of the advice columns.
|
||||||
|
s_pub: Selector,
|
||||||
|
}
|
||||||
|
// ANCHOR_END: chip-config
|
||||||
|
|
||||||
// ANCHOR: instructions-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> {
|
impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
type Num = Number<F>;
|
type Num = Number<F>;
|
||||||
|
@ -196,10 +175,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
mut layouter: impl Layouter<F>,
|
mut layouter: impl Layouter<F>,
|
||||||
value: Option<F>,
|
value: Option<F>,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
FieldConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut num = None;
|
let mut num = None;
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|
@ -224,10 +200,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
a: Self::Num,
|
a: Self::Num,
|
||||||
b: Self::Num,
|
b: Self::Num,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
FieldConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut out = None;
|
let mut out = None;
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|
@ -277,10 +250,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_public(&self, mut layouter: 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() {
|
let config = self.config();
|
||||||
FieldConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|| "expose public",
|
|| "expose public",
|
||||||
|
@ -319,7 +289,7 @@ struct MyCircuit<F: FieldExt> {
|
||||||
|
|
||||||
impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
||||||
// Since we are using a single chip for everything, we can just reuse its config.
|
// Since we are using a single chip for everything, we can just reuse its config.
|
||||||
type Config = FieldConfigEnum;
|
type Config = FieldConfig;
|
||||||
|
|
||||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||||
// We create the two advice columns that FieldChip uses for I/O.
|
// We create the two advice columns that FieldChip uses for I/O.
|
||||||
|
@ -328,14 +298,12 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
||||||
// We also need an instance column to store public inputs.
|
// We also need an instance column to store public inputs.
|
||||||
let instance = meta.instance_column();
|
let instance = meta.instance_column();
|
||||||
|
|
||||||
let mut field_chip = FieldChip::new();
|
FieldChip::configure(meta, advice, instance)
|
||||||
|
|
||||||
field_chip.configure(meta, advice, instance)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
|
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
|
||||||
let mut layouter = SingleChipLayouter::new(cs)?;
|
let mut layouter = SingleChipLayouter::new(cs)?;
|
||||||
let field_chip = FieldChip::<F>::construct(config, ());
|
let field_chip = FieldChip::<F>::construct(config);
|
||||||
|
|
||||||
// Load our private values into the circuit.
|
// Load our private values into the circuit.
|
||||||
let a = field_chip.load_private(layouter.namespace(|| "load a"), self.a)?;
|
let a = field_chip.load_private(layouter.namespace(|| "load a"), self.a)?;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
use halo2::{
|
use halo2::{
|
||||||
arithmetic::FieldExt,
|
arithmetic::FieldExt,
|
||||||
circuit::{layouter::SingleChipLayouter, Cell, Chip, Config, Layouter, Region},
|
circuit::{layouter::SingleChipLayouter, Cell, Chip, Layouter, Region},
|
||||||
dev::VerifyFailure,
|
dev::VerifyFailure,
|
||||||
plonk::{
|
plonk::{
|
||||||
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
|
Advice, Assignment, Circuit, Column, ConstraintSystem, Error, Instance, Permutation,
|
||||||
|
@ -13,6 +13,7 @@ use halo2::{
|
||||||
poly::Rotation,
|
poly::Rotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ANCHOR: field-instructions
|
||||||
/// A variable representing a number.
|
/// A variable representing a number.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Number<F: FieldExt> {
|
struct Number<F: FieldExt> {
|
||||||
|
@ -20,7 +21,6 @@ struct Number<F: FieldExt> {
|
||||||
value: Option<F>,
|
value: Option<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANCHOR: field-instructions
|
|
||||||
trait FieldInstructions<F: FieldExt>: AddInstructions<F> + MulInstructions<F> {
|
trait FieldInstructions<F: FieldExt>: AddInstructions<F> + MulInstructions<F> {
|
||||||
/// Variable representing a number.
|
/// Variable representing a number.
|
||||||
type Num;
|
type Num;
|
||||||
|
@ -98,20 +98,8 @@ struct FieldConfig {
|
||||||
// The selector for the public-input gate, which uses one of the advice columns.
|
// The selector for the public-input gate, which uses one of the advice columns.
|
||||||
s_pub: Selector,
|
s_pub: Selector,
|
||||||
|
|
||||||
add_config: AddConfigEnum,
|
add_config: AddConfig,
|
||||||
mul_config: MulConfigEnum,
|
mul_config: MulConfig,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum FieldConfigEnum {
|
|
||||||
Empty,
|
|
||||||
Config(FieldConfig),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config for FieldConfigEnum {
|
|
||||||
fn empty() -> Self {
|
|
||||||
Self::Empty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// ANCHOR END: field-config
|
// ANCHOR END: field-config
|
||||||
|
|
||||||
|
@ -122,18 +110,6 @@ struct AddConfig {
|
||||||
perm: Permutation,
|
perm: Permutation,
|
||||||
s_add: Selector,
|
s_add: Selector,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum AddConfigEnum {
|
|
||||||
Empty,
|
|
||||||
Config(AddConfig),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config for AddConfigEnum {
|
|
||||||
fn empty() -> Self {
|
|
||||||
Self::Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ANCHOR_END: add-config
|
// ANCHOR_END: add-config
|
||||||
|
|
||||||
// ANCHOR: mul-config
|
// ANCHOR: mul-config
|
||||||
|
@ -143,45 +119,33 @@ struct MulConfig {
|
||||||
perm: Permutation,
|
perm: Permutation,
|
||||||
s_mul: Selector,
|
s_mul: Selector,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum MulConfigEnum {
|
|
||||||
Empty,
|
|
||||||
Config(MulConfig),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config for MulConfigEnum {
|
|
||||||
fn empty() -> Self {
|
|
||||||
Self::Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ANCHOR END: mul-config
|
// ANCHOR END: mul-config
|
||||||
|
|
||||||
// ANCHOR: field-chip
|
// ANCHOR: field-chip
|
||||||
/// The top-level chip that will implement the `FieldInstructions`.
|
/// The top-level chip that will implement the `FieldInstructions`.
|
||||||
struct FieldChip<F: FieldExt> {
|
struct FieldChip<F: FieldExt> {
|
||||||
config: FieldConfigEnum,
|
config: FieldConfig,
|
||||||
_marker: PhantomData<F>,
|
_marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
// ANCHOR_END: field-chip
|
// ANCHOR_END: field-chip
|
||||||
|
|
||||||
// ANCHOR: add-chip
|
// ANCHOR: add-chip
|
||||||
struct AddChip<F: FieldExt> {
|
struct AddChip<F: FieldExt> {
|
||||||
config: AddConfigEnum,
|
config: AddConfig,
|
||||||
_marker: PhantomData<F>,
|
_marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
// ANCHOR END: add-chip
|
// ANCHOR END: add-chip
|
||||||
|
|
||||||
// ANCHOR: mul-chip
|
// ANCHOR: mul-chip
|
||||||
struct MulChip<F: FieldExt> {
|
struct MulChip<F: FieldExt> {
|
||||||
config: MulConfigEnum,
|
config: MulConfig,
|
||||||
_marker: PhantomData<F>,
|
_marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
// ANCHOR_END: mul-chip
|
// ANCHOR_END: mul-chip
|
||||||
|
|
||||||
// ANCHOR: add-chip-trait-impl
|
// ANCHOR: add-chip-trait-impl
|
||||||
impl<F: FieldExt> Chip<F> for AddChip<F> {
|
impl<F: FieldExt> Chip<F> for AddChip<F> {
|
||||||
type Config = AddConfigEnum;
|
type Config = AddConfig;
|
||||||
type Loaded = ();
|
type Loaded = ();
|
||||||
|
|
||||||
fn config(&self) -> &Self::Config {
|
fn config(&self) -> &Self::Config {
|
||||||
|
@ -196,13 +160,6 @@ impl<F: FieldExt> Chip<F> for AddChip<F> {
|
||||||
|
|
||||||
// ANCHOR: add-chip-impl
|
// ANCHOR: add-chip-impl
|
||||||
impl<F: FieldExt> AddChip<F> {
|
impl<F: FieldExt> AddChip<F> {
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
config: <Self as Chip<F>>::Config::empty(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
|
@ -211,7 +168,6 @@ impl<F: FieldExt> AddChip<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(
|
fn configure(
|
||||||
&mut self,
|
|
||||||
meta: &mut ConstraintSystem<F>,
|
meta: &mut ConstraintSystem<F>,
|
||||||
advice: [Column<Advice>; 2],
|
advice: [Column<Advice>; 2],
|
||||||
perm: Permutation,
|
perm: Permutation,
|
||||||
|
@ -227,13 +183,11 @@ impl<F: FieldExt> AddChip<F> {
|
||||||
s_add * (lhs + rhs + out * -F::one())
|
s_add * (lhs + rhs + out * -F::one())
|
||||||
});
|
});
|
||||||
|
|
||||||
let config = AddConfigEnum::Config(AddConfig {
|
AddConfig {
|
||||||
advice,
|
advice,
|
||||||
perm,
|
perm,
|
||||||
s_add,
|
s_add,
|
||||||
});
|
}
|
||||||
self.config = config.clone();
|
|
||||||
config
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ANCHOR END: add-chip-impl
|
// ANCHOR END: add-chip-impl
|
||||||
|
@ -247,10 +201,8 @@ impl<F: FieldExt> AddInstructions<F> for FieldChip<F> {
|
||||||
a: Self::Num,
|
a: Self::Num,
|
||||||
b: Self::Num,
|
b: Self::Num,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config().add_config.clone();
|
||||||
FieldConfigEnum::Config(config) => config.add_config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let add_chip = AddChip::<F>::construct(config, ());
|
let add_chip = AddChip::<F>::construct(config, ());
|
||||||
add_chip.add(layouter, a, b)
|
add_chip.add(layouter, a, b)
|
||||||
}
|
}
|
||||||
|
@ -265,10 +217,7 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
|
||||||
a: Self::Num,
|
a: Self::Num,
|
||||||
b: Self::Num,
|
b: Self::Num,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
AddConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut out = None;
|
let mut out = None;
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|
@ -321,7 +270,7 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
|
||||||
|
|
||||||
// ANCHOR: mul-chip-trait-impl
|
// ANCHOR: mul-chip-trait-impl
|
||||||
impl<F: FieldExt> Chip<F> for MulChip<F> {
|
impl<F: FieldExt> Chip<F> for MulChip<F> {
|
||||||
type Config = MulConfigEnum;
|
type Config = MulConfig;
|
||||||
type Loaded = ();
|
type Loaded = ();
|
||||||
|
|
||||||
fn config(&self) -> &Self::Config {
|
fn config(&self) -> &Self::Config {
|
||||||
|
@ -336,13 +285,6 @@ impl<F: FieldExt> Chip<F> for MulChip<F> {
|
||||||
|
|
||||||
// ANCHOR: mul-chip-impl
|
// ANCHOR: mul-chip-impl
|
||||||
impl<F: FieldExt> MulChip<F> {
|
impl<F: FieldExt> MulChip<F> {
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
config: <Self as Chip<F>>::Config::empty(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
|
@ -351,7 +293,6 @@ impl<F: FieldExt> MulChip<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(
|
fn configure(
|
||||||
&mut self,
|
|
||||||
meta: &mut ConstraintSystem<F>,
|
meta: &mut ConstraintSystem<F>,
|
||||||
advice: [Column<Advice>; 2],
|
advice: [Column<Advice>; 2],
|
||||||
perm: Permutation,
|
perm: Permutation,
|
||||||
|
@ -385,13 +326,11 @@ impl<F: FieldExt> MulChip<F> {
|
||||||
s_mul * (lhs * rhs + out * -F::one())
|
s_mul * (lhs * rhs + out * -F::one())
|
||||||
});
|
});
|
||||||
|
|
||||||
let config = MulConfigEnum::Config(MulConfig {
|
MulConfig {
|
||||||
advice,
|
advice,
|
||||||
perm,
|
perm,
|
||||||
s_mul,
|
s_mul,
|
||||||
});
|
}
|
||||||
self.config = config.clone();
|
|
||||||
config
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ANCHOR_END: mul-chip-impl
|
// ANCHOR_END: mul-chip-impl
|
||||||
|
@ -405,10 +344,7 @@ impl<F: FieldExt> MulInstructions<F> for FieldChip<F> {
|
||||||
a: Self::Num,
|
a: Self::Num,
|
||||||
b: Self::Num,
|
b: Self::Num,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config().mul_config.clone();
|
||||||
FieldConfigEnum::Config(config) => config.mul_config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let mul_chip = MulChip::<F>::construct(config, ());
|
let mul_chip = MulChip::<F>::construct(config, ());
|
||||||
mul_chip.mul(layouter, a, b)
|
mul_chip.mul(layouter, a, b)
|
||||||
}
|
}
|
||||||
|
@ -423,10 +359,7 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
|
||||||
a: Self::Num,
|
a: Self::Num,
|
||||||
b: Self::Num,
|
b: Self::Num,
|
||||||
) -> Result<Self::Num, Error> {
|
) -> Result<Self::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
MulConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut out = None;
|
let mut out = None;
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|
@ -479,7 +412,7 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
|
||||||
|
|
||||||
// ANCHOR: field-chip-trait-impl
|
// ANCHOR: field-chip-trait-impl
|
||||||
impl<F: FieldExt> Chip<F> for FieldChip<F> {
|
impl<F: FieldExt> Chip<F> for FieldChip<F> {
|
||||||
type Config = FieldConfigEnum;
|
type Config = FieldConfig;
|
||||||
type Loaded = ();
|
type Loaded = ();
|
||||||
|
|
||||||
fn config(&self) -> &Self::Config {
|
fn config(&self) -> &Self::Config {
|
||||||
|
@ -494,13 +427,6 @@ impl<F: FieldExt> Chip<F> for FieldChip<F> {
|
||||||
|
|
||||||
// ANCHOR: field-chip-impl
|
// ANCHOR: field-chip-impl
|
||||||
impl<F: FieldExt> FieldChip<F> {
|
impl<F: FieldExt> FieldChip<F> {
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
config: <Self as Chip<F>>::Config::empty(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
fn construct(config: <Self as Chip<F>>::Config, _loaded: <Self as Chip<F>>::Loaded) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
|
@ -509,7 +435,6 @@ impl<F: FieldExt> FieldChip<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(
|
fn configure(
|
||||||
&mut self,
|
|
||||||
meta: &mut ConstraintSystem<F>,
|
meta: &mut ConstraintSystem<F>,
|
||||||
advice: [Column<Advice>; 2],
|
advice: [Column<Advice>; 2],
|
||||||
instance: Column<Instance>,
|
instance: Column<Instance>,
|
||||||
|
@ -536,21 +461,16 @@ impl<F: FieldExt> FieldChip<F> {
|
||||||
s * (p + a * -F::one())
|
s * (p + a * -F::one())
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut add_chip = AddChip::new();
|
let add_config = AddChip::configure(meta, advice, perm.clone());
|
||||||
let add_config = add_chip.configure(meta, advice, perm.clone());
|
let mul_config = MulChip::configure(meta, advice, perm.clone());
|
||||||
|
|
||||||
let mut mul_chip = MulChip::new();
|
FieldConfig {
|
||||||
let mul_config = mul_chip.configure(meta, advice, perm.clone());
|
|
||||||
|
|
||||||
let config = FieldConfigEnum::Config(FieldConfig {
|
|
||||||
advice,
|
advice,
|
||||||
perm,
|
perm,
|
||||||
s_pub,
|
s_pub,
|
||||||
add_config,
|
add_config,
|
||||||
mul_config,
|
mul_config,
|
||||||
});
|
}
|
||||||
self.config = config.clone();
|
|
||||||
config
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ANCHOR_END: field-chip-impl
|
// ANCHOR_END: field-chip-impl
|
||||||
|
@ -564,10 +484,7 @@ impl<F: FieldExt> FieldInstructions<F> for FieldChip<F> {
|
||||||
mut layouter: impl Layouter<F>,
|
mut layouter: impl Layouter<F>,
|
||||||
value: Option<F>,
|
value: Option<F>,
|
||||||
) -> Result<<Self as FieldInstructions<F>>::Num, Error> {
|
) -> Result<<Self as FieldInstructions<F>>::Num, Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
FieldConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut num = None;
|
let mut num = None;
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|
@ -603,10 +520,7 @@ impl<F: FieldExt> FieldInstructions<F> for FieldChip<F> {
|
||||||
mut layouter: impl Layouter<F>,
|
mut layouter: impl Layouter<F>,
|
||||||
num: <Self as FieldInstructions<F>>::Num,
|
num: <Self as FieldInstructions<F>>::Num,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let config = match self.config() {
|
let config = self.config();
|
||||||
FieldConfigEnum::Config(config) => config.clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
layouter.assign_region(
|
layouter.assign_region(
|
||||||
|| "expose public",
|
|| "expose public",
|
||||||
|
@ -646,7 +560,7 @@ struct MyCircuit<F: FieldExt> {
|
||||||
|
|
||||||
impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
||||||
// Since we are using a single chip for everything, we can just reuse its config.
|
// Since we are using a single chip for everything, we can just reuse its config.
|
||||||
type Config = FieldConfigEnum;
|
type Config = FieldConfig;
|
||||||
|
|
||||||
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
|
||||||
// We create the two advice columns that FieldChip uses for I/O.
|
// We create the two advice columns that FieldChip uses for I/O.
|
||||||
|
@ -655,8 +569,7 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
||||||
// We also need an instance column to store public inputs.
|
// We also need an instance column to store public inputs.
|
||||||
let instance = meta.instance_column();
|
let instance = meta.instance_column();
|
||||||
|
|
||||||
let mut field_chip = FieldChip::new();
|
FieldChip::configure(meta, advice, instance)
|
||||||
field_chip.configure(meta, advice, instance)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
|
fn synthesize(&self, cs: &mut impl Assignment<F>, config: Self::Config) -> Result<(), Error> {
|
||||||
|
|
|
@ -9,22 +9,6 @@ use crate::{
|
||||||
|
|
||||||
pub mod layouter;
|
pub mod layouter;
|
||||||
|
|
||||||
/// A chip's configuration (i.e. columns, selectors, permutations).
|
|
||||||
pub trait Config: fmt::Debug + Clone {
|
|
||||||
/// An empty config
|
|
||||||
fn empty() -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A chip's loaded configuration (i.e. lookups, pre-computed fixed constants).
|
|
||||||
pub trait Loaded: fmt::Debug + Clone {
|
|
||||||
/// An empty loaded configuration
|
|
||||||
fn empty() -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Loaded for () {
|
|
||||||
fn empty() -> Self {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A chip implements a set of instructions that can be used by gadgets.
|
/// A chip implements a set of instructions that can be used by gadgets.
|
||||||
///
|
///
|
||||||
/// The chip stores state that is required at circuit synthesis time in
|
/// The chip stores state that is required at circuit synthesis time in
|
||||||
|
@ -38,13 +22,13 @@ pub trait Chip<F: FieldExt>: Sized {
|
||||||
/// during circuit synthesis, that can be derived during [`Circuit::configure`].
|
/// during circuit synthesis, that can be derived during [`Circuit::configure`].
|
||||||
///
|
///
|
||||||
/// [`Circuit::configure`]: crate::plonk::Circuit::configure
|
/// [`Circuit::configure`]: crate::plonk::Circuit::configure
|
||||||
type Config: Config;
|
type Config: fmt::Debug + Clone;
|
||||||
|
|
||||||
/// A type that holds any general chip state that needs to be loaded at the start of
|
/// A type that holds any general chip state that needs to be loaded at the start of
|
||||||
/// [`Circuit::synthesize`]. This might simply be `()` for some chips.
|
/// [`Circuit::synthesize`]. This might simply be `()` for some chips.
|
||||||
///
|
///
|
||||||
/// [`Circuit::synthesize`]: crate::plonk::Circuit::synthesize
|
/// [`Circuit::synthesize`]: crate::plonk::Circuit::synthesize
|
||||||
type Loaded: Loaded;
|
type Loaded: fmt::Debug + Clone;
|
||||||
|
|
||||||
/// The chip holds its own configuration.
|
/// The chip holds its own configuration.
|
||||||
fn config(&self) -> &Self::Config;
|
fn config(&self) -> &Self::Config;
|
||||||
|
|
Loading…
Reference in New Issue