This repository has been archived by the owner on Nov 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
239 changed files
with
42,903 additions
and
259 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Sphinx build info version 1 | ||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. | ||
config: 02af6eb916b22e1e52b25f8425e8f337 | ||
tags: 645f666f9bcd5a90fca523b33c5a78b7 |
104 changes: 104 additions & 0 deletions
104
book/_build/html/_sources/chiquito_programming_model.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Chiquito programming model | ||
|
||
## ZKP as trace | ||
|
||
ZKP generates proofs that an algorithm has been execute correctly. | ||
|
||
The best way we can analyse a particular execution of an algorithm is by its trace. | ||
|
||
For example: | ||
|
||
```python= | ||
def bubbleSort(arr): | ||
n = len(arr) | ||
for i in range(n-1): | ||
for j in range(0, n-i-1): | ||
if arr[j] > arr[j + 1]: | ||
arr[j], arr[j + 1] = arr[j + 1], arr[j] | ||
``` | ||
|
||
A trace for a particular input is the actual steps that are executed in order. | ||
|
||
For example if `arr = [64, 34, 25, 12, 22, 11, 90]`, the trace is: | ||
|
||
``` | ||
set n to length of arr which is 7 | ||
set i to 1 | ||
set j to 0 | ||
compare arr[j] > arr[j+1] => arr[0] > arr[1] => 64 > 34 => true | ||
set arr[0] to arr[1] and arr[1] to arr[0] => arr[0] = 34, arr[1] = 64 | ||
// and so on... | ||
``` | ||
|
||
It is important to understand that each step has a pre-state, with the values of the variables before the execution of the step, and a post-state with the values of the variables after the execution of the step. The post-state of a step is the pre-state of the next one. | ||
|
||
If we include the states indented: | ||
``` | ||
arr = [64, 34, 25, 12, 22, 11, 90] | ||
n = ?, i = ?, j = ? | ||
set n to lenght of arr which is 7 | ||
arr = [64, 34, 25, 12, 22, 11, 90] | ||
n = 7, i = ?, j = ? | ||
set i to 1 | ||
arr = [64, 34, 25, 12, 22, 11, 90] | ||
n = 7, i = 1, j = ? | ||
set j to 0 | ||
arr = [64, 34, 25, 12, 22, 11, 90] | ||
n = 7, i = 1, j = 0 | ||
compare arr[j] > arr[j+1] => arr[0] > arr[1] => 64 > 34 => true | ||
arr = [64, 34, 25, 12, 22, 11, 90] | ||
n = 7, i = 1, j = 0 | ||
set arr[0] to arr[1] and arr[1] to arr[0] => arr[0] = 34, arr[1] = 64 | ||
arr = [34, 64, 25, 12, 22, 11, 90] | ||
n = 7, i = 1, j = 0 | ||
// and so on... | ||
``` | ||
|
||
## ZKP circuit as a trace checker | ||
|
||
We can see a ZKP circuit as a series of step types, and their constraints relative to the post-state and pre-state, and also potentially some internal values. | ||
|
||
For example, we can have the step type `set $variable to $value` and the constraint would be that the post state of `$variable` should be `$value`. | ||
|
||
## ZKP witness as a trace | ||
|
||
In the same way, we can see the witness as a the trace of a computation plus some information about the states between the steps. | ||
|
||
The programming model in chiquito follows the idea that every zero knowledge proof represents a program (the setup), which can have many computations (the trace) that is proven for a certain input, output and intermediate values (the witness). | ||
|
||
## Step types and step instances | ||
|
||
A trace is made of a sequence of step instances or trace steps, that contains the data about that step instance. | ||
|
||
Each step instance belong to a step type. A step types contains rules (or constraints) about whether a step instance is valid in relation to its data and the data of other step instances relative to it. | ||
|
||
Step types are part of the setup, which means that they cannot change between proofs, but this circuit can proof all possible traces, as they are part of the witness. | ||
|
||
## Signals and rotations | ||
|
||
Signals represent are elements of the witness that have a independent value for each trace step, but in chiquito paradigm you can see them as variables on the trace steps. | ||
|
||
Rotation refer to the capability of creating rules that involved the value of signals in other trace steps with an offset relative to the trace step, not just the value of a signal. A rotation of 0, represent the value of the signal in the same trace step, a rotation of 1 in the next step, a rotation of -1 in the previous step, in general any rotation number is posible. | ||
|
||
## Types of signals | ||
|
||
There are two types of signals that are shared between the step types, **forward** signals and **shared** signals. The difference is that forward signals can only rotate to the next step, while shared signals can rotate to any number of steps. However, circuits that only use forward signals are more efficient in some cases, so you should try to use only forward signals. | ||
|
||
**Internal** signals are not shared between step types, and belong to a specific step type and cannot be rotated. | ||
|
||
There is a special type of signal called **fixed**, that is not part of the witness and it is used to contain constants. | ||
|
||
| | Scope | Rotation | Role | | ||
| -------- | ---------------- | --------- | ------- | | ||
| Forward | All step types | Only next | Witness | | ||
| Shared | All step types | Any | Witness | | ||
| Internal | Single step type | None | Witness | | ||
| Fixed | All step types | Any | Setup | | ||
|
||
## Putting everything together | ||
|
||
TODO: Diagram | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# What is chiquito? | ||
|
||
Chiquito is a high-level structured language for implementing zero knowledge proof applications. | ||
|
||
Chiquito is being implemented in the DSL Working Group of PSE, Ethereum Foundation. | ||
|
||
<p align="center"> | ||
<img src="https://hackmd.io/_uploads/HyuEr1cB2.png" width="180" height="80" alt="Image 2"> | ||
| ||
<img src="https://hackmd.io/_uploads/HyZ0rycS2.png" width="70" height="100" alt="Image 3"> | ||
</p> |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
# Python syntax | ||
|
||
## Constraint builder | ||
|
||
One of the most important parts of defining a circuit is the constraints. The basis for writing constraints are arithmetic operations with signals. You use the operators `*`, `+` and `-` with numbers and signals. For example: | ||
|
||
`a + 1 * b` | ||
|
||
When you need to do a rotation on a signal you can use the operators `.next()`, `prev()` and or `.rot(n)`. For example: | ||
|
||
`a + 1 * b.next()` | ||
|
||
There are several helper functions to define constraints: | ||
+ `cb_and([a1 ... an])`: And operator | ||
+ `cb_or([a1 ... an])`: Or operator | ||
+ `xor(a, b)`: Xor operator | ||
+ `eq(a, b)`: Arithmetic equality. | ||
+ `select(selector, when_true, when_false)`: trinary operator | ||
+ `when(selector, when_true)`: Logical imply. | ||
+ `unless(selector, when_false)`: Logical imply when !selector. | ||
+ `cb_not(a)`: Not operator. | ||
+ isz(a): Equal to zero. | ||
+ `if_next_step(step_type, a)`: If next step is step_type, implies a. | ||
+ `next_step_must_be(step_type)`: Enforces next step must be step_type. | ||
+ `next_step_must_not_be(step_type)`: Enforces next step must not be step_type. | ||
|
||
In the current version of chiquito these operator cannot be combined arbitrarily, there is a solution in the works. For example `cb_and` cannot have operands that are `eq`. | ||
|
||
## Defining a step | ||
|
||
A chiquito circuit is made of steps, this is how we define steps: | ||
|
||
```python= | ||
class AStep(StepType): | ||
def setup(self): | ||
# setup: rules about a valid step | ||
def wg(self, a, b, c): | ||
# witness generation: set data for a step instance | ||
``` | ||
|
||
For the setup we need to define constraints that define which step witness is valid and also define the internal signals. For example: | ||
|
||
```python= | ||
class AStep(StepType): | ||
def setup(self): | ||
self.c = self.internal("c") | ||
``` | ||
|
||
To access shared signals we can do it with `self.circuit.signal_identifier`. | ||
|
||
For the constraints that we can use the method `constr`. For example: | ||
|
||
```python= | ||
class AStep(StepType): | ||
def setup(self): | ||
self.constr(eq(self.circuit.a, self.circuit.b * 3)) | ||
self.constr(when(self.circuit.a, eq(self.circuit.b, self.c)) | ||
# ... | ||
``` | ||
|
||
The first constraint means that `a` must be equal to `b times 3`. The second that when `a` value is `1` then `b` must be equal to `c`. | ||
|
||
When you have a rotation you should use the method `transition`. For example: | ||
|
||
```python= | ||
class AStep(StepType): | ||
def setup(self): | ||
self.transition(eq(self.circuit.a, self.circuit.b.next() * 3)) | ||
self.transition(when(self.circuit.a, eq(self.circuit.b.next(), self.c)) | ||
# ... | ||
``` | ||
|
||
|
||
For the data of one step instance in the `wg` method we must use the `assign` method to assign all signals. | ||
|
||
```python= | ||
class AStep(StepType): | ||
def wg(self, a_val, b_val): | ||
self.assign(self.circuit.a, a_val) | ||
self.assign(self.circuit.b, b_val) | ||
self.assign(self.c, a_val + b_val) | ||
# ... | ||
``` | ||
|
||
The method `wg` can have any parameters, and do any computation to calculate the assignations. But signals cannot be rotated for assignation, you can only assign the current step. | ||
|
||
## Defining the circuit | ||
|
||
To put everything together we define the circuit, also with two methods. | ||
|
||
```python= | ||
class ACircuit(Circuit): | ||
def setup(self): | ||
# Define shared signals and step types used, number of total steps plus more setup configuration. | ||
def trace(self, arg1, arg2): | ||
# Define algorithm to create the trace from the input. | ||
``` | ||
|
||
For the setup we defined shared signals, step types and number of steps in the trace. For example: | ||
|
||
```python= | ||
class ACircuit(Circuit): | ||
def setup(self): | ||
# shared signals | ||
self.a = self.forward("a") | ||
self.b = self.forward("b") | ||
self.n = self.forward("n") | ||
# step types | ||
self.a_step = self.step_type(AStep(self, "a_step")) | ||
self.b_step = self.step_type(BStep(self, "b_step")) | ||
self.c_step = self.step_type(CStep(self, "c_step")) | ||
# number of trace steps | ||
self.pragma_num_steps(10) | ||
# ... | ||
``` | ||
|
||
There are many optional things that you can also configure in the circuit setup: | ||
|
||
```python= | ||
class ACircuit(Circuit): | ||
def setup(self): | ||
self.pragma_first_step(self.a_step) | ||
self.pragma_last_step(self.b_step) | ||
self.expose(self.b, Last()) | ||
self.expose(self.n, Last()) | ||
# ... | ||
``` | ||
|
||
Then, we should define `trace`, this method add step instances or trace steps to create a particular trace. The most important method is `add()`, the first parameter is a step type, and the rest are the parameters to the step type `wg` method. This method adds a trace step | ||
|
||
For example: | ||
|
||
```python= | ||
class ACircuit(Circuit): | ||
def trace(self, n): | ||
self.add(self.a_step, 1, 1, n) | ||
a = 1 | ||
b = 2 | ||
for i in range(1, n): | ||
self.add(self.b_step, a, b, n) | ||
prev_a = a | ||
a = b | ||
b += prev_a | ||
while self.needs_padding(): | ||
self.add(self.b_step, a, b, n) | ||
# ... | ||
``` |
Oops, something went wrong.