Documentation ¶
Overview ¶
`plonk` provides a dedicated Wizard utility to embed a gnark Plonk circuit in a Wizard's compiled IOP. This utility can be used by passing the plonk.PlonkCheck function.
For instance, say we have a gnark circuit that can verify digital signatures and which takes a set of message hashes and public keys as public inputs. The user can provide a column allegedly containing all the public input and a gnark circuit performing the above-mentioned signature verification.
The user can call the plonk.PlonkCheck function by passing the column and the circuit alongside a wizard.CompiledIOP object. The utility will build all the necessary columns and declare all the necessary constraints to emulate the circuit's satisfiability within the currently compiled IOP.
This comes in handy in situation where we which to prove complex relations that are difficult to express directly in the form of a Wizard-IOP but easier to express in a language that is more expressive. In the case, of Linea's zkEVM, this is used for the ECDSA verification and the precompiles.
The package optionally offers optimization when,
- declaring multiple instances of the same circuit
- deferring the range-checks outside of the circuit so that they can be implemented directly using [bigrange.BigRange] which has less overheads than in-circuit range-checks.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func PlonkCheck ¶
func PlonkCheck( comp *wizard.CompiledIOP, name string, round int, circuit frontend.Circuit, maxNbInstance int, options ...Option, ) compilationCtx
PlonkCheck adds a PLONK circuit in the wizard. Namely, the function takes a frontend.Circuit parameter, a PLONK witness assigner (i.e. a function that returns the PLONK witness to be used as an input for the solver). It compiles the circuit and construct a set of column and constraints reflecting the satisfiability of the provided PLONK circuit within the current Wizard. This is used for the precompiles and for ECDSA verification since these use-cases would require a very complex design if we wanted to implement them directly into the Wizard instead of Plonk.
The user can provide one or more assigner for the same circuit to mean that we want to call the same circuit multiple times. In this case, the function optimizes the generated Wizard to commit only once to the preprocessed polynomials (qL, qR, etc...). This additionally allows batching certain parts of the protocol such as the copy-constraints argument which will be run only once over a random linear combination of the witnesses.
The user can provide an identifying string `name` to the function. The name will be appended to all generated columns and queries name to carry some context to where these queries and columns come from.
Types ¶
type Alignment ¶
type Alignment struct { *CircuitAlignmentInput // IsActive is a column which indicates that the row is active. // Can be used to perform constrain cancellation. IsActive ifaces.Column // CircuitInput is the aligned input to the circuit with every instance // input padded to power of two. CircuitInput ifaces.Column // FullCircuitInputMask is a precomputed column which masks all public inputs for the circuit. FullCircuitInputMask ifaces.Column // ActualCircuitInputMask is an assigned column which masks public inputs // for the circuit coming from the alignment input. ActualCircuitInputMask ifaces.Column // NbInput indicates the actual number of inputs for a circuit. Property of // this structure as we obtain it after compiling the circuit. NbInput int // contains filtered or unexported fields }
Alignment is the prepared structure where the Data field is aligned to gnark circuit PI column. It considers the cases where we call multiple instances of the circuit so that the inputs for every circuit is padded to power of two length.
func DefineAlignment ¶
func DefineAlignment(comp *wizard.CompiledIOP, toAlign *CircuitAlignmentInput) *Alignment
DefineAlignment allows to align data from a column with a mask to PI input column of PLONK-in-Wizard instance.
func (*Alignment) Assign ¶
func (a *Alignment) Assign(run *wizard.ProverRuntime)
Assign assigns the colums in the Alignment structure at runtime.
type CircuitAlignmentInput ¶
type CircuitAlignmentInput struct { // Name is a unique name for the alignment for identification purposes. Name string // Round is the round at which we should call the PLONK solver. Round int // DataToCircuitMask is a binary vector which indicates which data should be // given as an input to a PLONK-in-Wizard instance as a public input. // // NB! We do not consider the padding to power of two here. If the input // data is not full length then we use InputFiller to compute the missing // values. DataToCircuitMask ifaces.Column // DataToCircuit is the actual data to provide as input to PLONK-in-Wizard // instance as public input. It is up to the caller to ensure that the // number of masked elements is nbPublicInputs*nbCircuitInstances, as it is // circuit specific. Most importantly, if the input data is less then the // caller must pad with valid inputs according to the circuit (dummy values, // zero values, indicator etc)! // // NB! See the comment for DataToCircuitMask. DataToCircuit ifaces.Column // Circuit is the gnark circuit for which we provide the public input. Circuit frontend.Circuit // NbCircuitInstances is the number of gnark circuit instances we call. We // have to consider that for every circuit instance the PI column length has // to be padded to a power of two. NbCircuitInstances int // PlonkOptions are optional options to the plonk-in-wizard checker. See [Option]. PlonkOptions []Option // InputFiller returns an element to pad in the public input for the // circuit in case DataToCircuitMask is not full length of the circuit // input. If it is nil, then we use zero value. InputFiller func(circuitInstance, inputIndex int) field.Element // contains filtered or unexported fields }
CircuitAlignmentInput is the input structure for the alignment of the data to the circuit. It contains the circuit for which the data is aligned, the data to align and the mask which indicates which data should be given as input to the circuit.
The alignment is done in a way that the data is padded to power of two length for every circuit instance.
func (*CircuitAlignmentInput) Assign ¶
func (ci *CircuitAlignmentInput) Assign(run *wizard.ProverRuntime, i int) (private, public witness.Witness, err error)
Assign returns the witness for the circuit for solving. The witness is read from the columns and if it is not long enough, then filled with dummy values. Implements WitnessAssigner.
func (*CircuitAlignmentInput) NbInstances ¶
func (ci *CircuitAlignmentInput) NbInstances() int
func (*CircuitAlignmentInput) NumEffWitnesses ¶
func (ci *CircuitAlignmentInput) NumEffWitnesses(run *wizard.ProverRuntime) int
type Option ¶
type Option func(*compilationCtx)
PlonkOption allows modifying Plonk circuit arithmetization.
func WithRangecheck ¶
WithRangecheck allows bridging range checking from gnark into Wizard. The total of bits being range-checked are nbBits*nbLimbs. If addGateForRangeCheck is true, then new gates are added for wires not present in existing gates.
type PlonkInWizardProverAction ¶
type PlonkInWizardProverAction interface {
Run(run *wizard.ProverRuntime, wa WitnessAssigner)
}
PlonkInWizardProverAction is an interface representing prover runtime action to assign the Plonk circuit and run the gnark solver to generate the witness.
type WitnessAssigner ¶
type WitnessAssigner interface { NumEffWitnesses(run *wizard.ProverRuntime) int Assign(run *wizard.ProverRuntime, i int) (private, public witness.Witness, err error) }
WitnessAssigner allows obtaining witness assignment for a circuit.
func NewSafeCircuitAssigner ¶
func NewSafeCircuitAssigner(circuit frontend.Circuit, assigners ...func() frontend.Circuit) WitnessAssigner
NewSafeCircuitAssigner returns a WitnessAssigner that returns the private and public witness of the circuit. The assign function is called to get the assignment of the circuit.
The function returns an error if the circuit and the assignment do not have the same type. For the unsafe version use NewUnsafeCircuitAssigner.
func NewUnsafeCircuitAssigner ¶
func NewUnsafeCircuitAssigner(assigners ...func() frontend.Circuit) WitnessAssigner
NewUnsafeCircuitAssigner returns a WitnessAssigner that returns the private and public witness of the circuit. The assign function is called to get the assignment of the circuit.
The function does not check if the circuit and the assignment have the same type. For the safe version use NewSafeCircuitAssigner.