Files
chiquito/examples/mimc7.py
Steve Wang d0933d7e4f Jupyter Book (#161)
Ready for review. @leolara 

To run this:
```
pip install jupyter-book
jupyter-book build book # book is the sub-directory where all the book stuffs live in
```
A `_build` folder with `html` artifacts should be created. Terminal
should print out directions on how to open the build files in the
browser. For example, pasting a local directory like
`file:///Users/steve/Documents/repo/chiquito-6_2_23_v10/chiquito/book/_build/html/index.html`
into the browser bar.

Once we are good with the content and merge. I shall create a follow up
PR that add CI to auto builder and host the book via gh-pages, though it
could take quite some tweaking as our gh-pages branch currently builds
and hosts the Rust doc.

CI will follow something like the following:
https://jupyterbook.org/en/stable/start/publish.html
2023-10-26 11:09:51 +00:00

171 lines
5.4 KiB
Python

from __future__ import annotations
from chiquito.dsl import SuperCircuit, Circuit, StepType
from chiquito.cb import eq, table
from chiquito.util import F
from mimc7_constants import ROUND_CONSTANTS
ROUNDS = 91
# It's the best practice to wrap all values in F, even though the `assign` functions automatically wrap values in F.
class Mimc7Constants(Circuit):
def setup(self):
self.pragma_num_steps(ROUNDS)
self.lookup_row = self.fixed("constant row")
self.lookup_c = self.fixed("constant value")
self.lookup_table = self.new_table(
table().add(self.lookup_row).add(self.lookup_c)
)
def fixed_gen(self):
for i, round_key in enumerate(ROUND_CONSTANTS):
self.assign(i, self.lookup_row, F(i))
self.assign(i, self.lookup_c, F(round_key))
class Mimc7FirstStep(StepType):
def setup(self):
self.xkc = self.internal("xkc")
self.y = self.internal("y")
self.c = self.internal("c")
self.constr(eq(self.circuit.x + self.circuit.k + self.c, self.xkc))
self.constr(
eq(
self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc,
self.y,
)
)
self.transition(eq(self.y, self.circuit.x.next()))
self.transition(eq(self.circuit.k, self.circuit.k.next()))
self.transition(eq(self.circuit.row, 0))
self.transition(eq(self.circuit.row + 1, self.circuit.row.next()))
self.add_lookup(
self.circuit.constants_table.apply(self.circuit.row).apply(self.c)
)
def wg(self, x_value, k_value, c_value, row_value):
self.assign(self.circuit.x, F(x_value))
self.assign(self.circuit.k, F(k_value))
self.assign(self.c, F(c_value))
self.assign(self.circuit.row, F(row_value))
xkc_value = F(x_value + k_value + c_value)
self.assign(self.xkc, F(xkc_value))
self.assign(self.y, F(xkc_value**7))
class Mimc7Step(StepType):
def setup(self):
self.xkc = self.internal("xkc")
self.y = self.internal("y")
self.c = self.internal("c")
self.constr(eq(self.circuit.x + self.circuit.k + self.c, self.xkc))
self.constr(
eq(
self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc
* self.xkc,
self.y,
)
)
self.transition(eq(self.y, self.circuit.x.next()))
self.transition(eq(self.circuit.k, self.circuit.k.next()))
self.transition(eq(self.circuit.row + 1, self.circuit.row.next()))
self.add_lookup(
self.circuit.constants_table.apply(self.circuit.row).apply(self.c)
)
def wg(self, x_value, k_value, c_value, row_value):
self.assign(self.circuit.x, F(x_value))
self.assign(self.circuit.k, F(k_value))
self.assign(self.c, F(c_value))
self.assign(self.circuit.row, F(row_value))
xkc_value = F(x_value + k_value + c_value)
self.assign(self.xkc, F(xkc_value))
self.assign(self.y, F(xkc_value**7))
class Mimc7LastStep(StepType):
def setup(self):
self.out = self.internal("out")
self.constr(eq(self.circuit.x + self.circuit.k, self.out))
def wg(self, x_value, k_value, _, row_value):
self.assign(self.circuit.x, F(x_value))
self.assign(self.circuit.k, F(k_value))
self.assign(self.circuit.row, F(row_value))
self.assign(self.out, F(x_value + k_value))
class Mimc7Circuit(Circuit):
def setup(self):
self.x = self.forward("x")
self.k = self.forward("k")
self.row = self.forward("row")
self.mimc7_first_step = self.step_type(Mimc7FirstStep(self, "mimc7_first_step"))
self.mimc7_step = self.step_type(Mimc7Step(self, "mimc7_step"))
self.mimc7_last_step = self.step_type(Mimc7LastStep(self, "mimc7_last_step"))
self.pragma_first_step(self.mimc7_first_step)
self.pragma_last_step(self.mimc7_last_step)
self.pragma_num_steps(ROUNDS + 2 - 1)
def trace(self, x_in_value, k_value):
c_value = F(ROUND_CONSTANTS[0])
x_value = F(x_in_value)
row_value = F(0)
self.add(self.mimc7_first_step, x_value, k_value, c_value, row_value)
for i in range(1, ROUNDS):
row_value += F(1)
x_value += F(k_value + c_value)
x_value = F(x_value**7)
c_value = F(ROUND_CONSTANTS[i])
self.add(self.mimc7_step, x_value, k_value, c_value, row_value)
row_value += F(1)
x_value += F(k_value + c_value)
x_value = F(x_value**7)
self.add(self.mimc7_last_step, x_value, k_value, c_value, row_value)
class Mimc7SuperCircuit(SuperCircuit):
def setup(self):
self.mimc7_constants = self.sub_circuit(Mimc7Constants(self))
self.mimc7_circuit = self.sub_circuit(
Mimc7Circuit(self, constants_table=self.mimc7_constants.lookup_table)
)
def mapping(self, x_in_value, k_value):
self.map(self.mimc7_circuit, x_in_value, k_value)
mimc7 = Mimc7SuperCircuit()
mimc7_super_witness = mimc7.gen_witness(F(1), F(2))
# for key, value in mimc7_super_witness.items():
# print(f"{key}: {str(value)}")
mimc7.halo2_mock_prover(mimc7_super_witness, k=10)