123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186(*****************************************************************************)(* *)(* MIT License *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)includeLang_coreincludeLang_stdlib(** Plompiler is an OCaml eDSL for writing PlonK arithmetic circuits
(see {!Lib_plonk.Main_protocol} for an introduction to PlonK circuits).
The eDSL is implemented following a tagless-final approach and
is split into a core language and a standard library, each
described as a module type. The core is defined by {!Lang_core.COMMON}
while the standard library is defined by {!Lang_stdlib.LIB}.
The Plompiler library is defined around three main parameterized types.
First, ['a t] is a monadic type that represents a Plompiler computation
returning a value of type ['a]. Second, ['a repr] is the Plompiler
representation of a value of type ['a]. Finally, ['a input] represents
an input to a circuit of type ['a]. These two final types are related:
an ['a input] will become an ['a repr] once inputted into a circuit.
A Plompiler program, then, will be a functor over [LIB]. The general
structure of of a Plompiler program is:
{[
module Program (L : LIB) = struct
open L
let logic : 'a repr -> 'b repr -> unit repr t = ...
let prog : 'a input -> 'b input -> unit repr t =
fun a b ->
let* a = input ~kind:'Public a in
let* b = input b in
logic a b
end
]}
Here, the first function defines the [logic] of the program,
while [prog] declares the inputs, the first of which is public.
A module implementing the `LIB` signature can be seen as an interpreter of
the language. Concretely, two such interpreters are defined: {!LibResult}
and {!LibCircuit}. The first runs a Plompiler program with pure values,
i.e. without generating a circuit. This means that, for this interpreter,
['a repr] is essentially ['a]. The second, {!LibCircuit}, is the actual
circuit backend. Here, ['a repr] will represent a PlonK wire carrying
a value of type ['a].
The rest of the library is implemented through the following modules:
{ul
{li {!Csir}: defines the Constraint System intermediate representation,
which is an abstract representation for PlonK constraint systems.
This is the target of the {!LibCircuit} interpreter, and can be converted
into a PlonK circuit.
}
{li {!Encoding}: encoders/decoders for usage of structured data types
in circuits. Simplifies data manipulation and the definition of inputs.
}
{li {!Optimizer}: low-level generic optimizer of [Csir] constraint
systems.
}
{li {!Solver}: description and interpretation of the programs needed to
populate the PlonK witness for a Plompiler circuit given the initial
inputs.}
{li [Gadget_X]: building blocks for circuits, mainly implementing
cryptographic primitives.}
}
*)(** Pure-value backend. Used to check the semantics of {!LibCircuit} in the
tests. *)moduleLibResult:sigincludeLIB(** [get_result prog] runs the Plompiler computation [prog] and returns
its result. The result is wrapped in the [Input.t] structure as this
describes the possible values that Plompiler can deal with. *)valget_result:'areprt->'aInput.tend=structincludeResultincludeLib(Result)end(** Circuit producing backend. *)moduleLibCircuit:sigincludeLIB(** [deserialize scalars inpt] populates the structure of
[inpt] with the values from [scalars]. *)valdeserialize:S.tarray->'aInput.t->'aInput.t(** [get_inputs c] returns the initial inputs for the computation [c],
together with the number of those inputs that are public.
This fuction is useful when the inputs used for the circuit definition
have meaningful values (in contrast to the often used dummy inputs, as
explained in {!Lang_core.COMMON.Input}).
*)valget_inputs:'areprt->S.tarray*int(** Constraint system and auxiliary data resulting from a
Plompiler program. *)typecs_result={nvars:int;(** Number of variables in the [cs] witness *)free_wires:intlist;(** Wire indices that are not used in the [cs],
they have been freed by the optimizer. *)cs:Csir.CS.t;(** Constraint system *)public_input_size:int;input_com_sizes:intlist;(** Sizes for input commitments *)tables:Csir.Table.tlist;(** Tables for lookups *)range_checks:(int*(int*int)list)list;(** Range checks following the format:
index of wire * (index in wire * bound) *)range_checks_labels:(stringlist*int)list;(** label trace that creates a range-check and
the size of the range-check *)solver:Solver.t;(** Solver for the [cs] *)}[@@derivingrepr](** [get_cs ?optimize c] runs the computation [c] generating a
constraint system. If [optimize] is [true], it will run the
optimizer on the produced CS. The optimized CS will be
cached in {!Utils.circuit_dir}, using the [TMPDIR] environment
variable. *)valget_cs:?optimize:bool->'areprt->cs_resultend=structincludeCircuitincludeLib(Circuit)endmoduleGadget=structmoduletypeHASH=Hash_sig.HASHmoduleAnemoi128=Gadget_anemoi.Anemoi128moduleAnemoiJive_128_1=Gadget_anemoi.MakemodulePoseidon128=Gadget_poseidon.Poseidon128modulePoseidon252=Gadget_poseidon.Poseidon252modulePoseidonFull=Gadget_poseidon.PoseidonFullmoduleMerkle=Gadget_merkle.MakemoduleMerkle_narity=Gadget_merkle_naritymoduleJubjubEdwards=Gadget_edwards.MakeAffine(Mec.Curve.Jubjub.AffineEdwards)moduleJubjubWeierstrass=Gadget_weierstrass.MakeAffine(Mec.Curve.Jubjub.AffineWeierstrass)moduleSchnorr=Gadget_schnorr.Make(Mec.Curve.Jubjub.AffineEdwards)moduleEdwards25519=Gadget_edwards25519.MakeEdwards25519moduleEd25519=Gadget_ed25519.Ed25519moduleBlake2s=Gadget_blake2s.Blake2smoduleArithMod25519=Gadget_mod_arith.ArithMod25519moduleArithMod64=Gadget_mod_arith.ArithMod64moduleSha256=Gadget_sha2.SHA256moduleSha512=Gadget_sha2.SHA512endincludeGadgetmoduleUtils=UtilsmoduleLinear_algebra=Linear_algebramoduleOptimizer=OptimizermoduleSolver=SolvermoduleBounded=BoundedmoduleCsir=Csir