mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
cleaned up old crypto research from root dir
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
---
|
||||
title: Halo 1 Arithmetization Polynomials Expansion
|
||||
author: Amir Taaki
|
||||
header-includes: |
|
||||
- \newcommand{\vec}[1]{\mathbf{#1}}
|
||||
---
|
||||
|
||||
Halo 1 constraints consist of multiplication constraints of the form
|
||||
$$\vec{a_i} \cdot \vec{b_i} = \vec{c_i}$$
|
||||
and linear addition constraints of the form
|
||||
$$\left(\sum_{i = 1}^N \vec{a_i} \cdot (\vec{u_q})_i\right) + \left(\sum_{i = 1}^N \vec{b_i} \cdot (\vec{v_q})_i\right) + \left(\sum_{i = 1}^N \vec{c_i} \cdot (\vec{w_q})_i\right) = \vec{k_q}$$
|
||||
|
||||
We embed all these constraints using different powers of $Y$ so they are linearly independent.
|
||||
|
||||
$$\sum_{i = 1}^N \vec{a_i} \cdot Y^N u_i(Y) + \sum_{i = 1}^N \vec{b_i} \cdot Y^N v_i(Y) + \sum_{i = 1}^N \vec{c_i} \cdot (Y^N w_i(Y) - Y^i - Y^{-i}) + \sum_{i = 1}^N \vec{a_i b_i} \cdot (Y^i + Y^{-i}) - Y^N k(Y) = 0 $$
|
||||
|
||||
where we define the polynomials
|
||||
|
||||
$$u_i(Y) = \sum_{q = 1}^Q Y^q (\vec{u}_q)_i \qquad v_i(Y) = \sum_{q = 1}^Q Y^q (\vec{v}_q)_i$$
|
||||
$$w_i(Y) = \sum_{q = 1}^Q Y^q (\vec{w}_q)_i \qquad k(Y) = \sum_{q = 1}^Q Y^q \vec{k}_q$$
|
||||
|
||||
\begin{alignat*}{2}
|
||||
r(X, Y) &= && \sum_{i = 1}^N \vec{a}_i X^i Y^i + \sum_{i = 1} \vec{b}_i X^{-i} Y^{-i} + \sum_{i = 1}^N \vec{c}_i X^{-i - N} Y^{-i - N} \\
|
||||
&= \; &&\vec{a_1} XY + \vec{a_2} X^2 Y^2 + \cdots + \vec{a_N} X^N Y^N \\
|
||||
& && + \vec{b_1} X^{-1} Y^{-1} + \vec{b_2} X^{-2} Y^{-2} + \cdots + \vec{b_N} X^{-N} Y^{-N} \\
|
||||
& && + \vec{c_1} X^{-1 -N} Y^{-1 -N} + \vec{c_2} X^{-2-N} Y^{-2-N} + \cdots + \vec{c_N} X^{-N-N} Y^{-N-N}
|
||||
\end{alignat*}
|
||||
|
||||
\begin{alignat*}{2}
|
||||
r(X, 1) &= && \sum_{i = 1}^N \vec{a}_i X^i + \sum_{i = 1} \vec{b}_i X^{-i} + \sum_{i = 1}^N \vec{c}_i X^{-i - N} \\
|
||||
&= \; &&\vec{a_1} X + \vec{a_2} X^2 + \cdots + \vec{a_N} X^N \\
|
||||
& && + \vec{b_1} X^{-1} + \vec{b_2} X^{-2} + \cdots + \vec{b_N} X^{-N} \\
|
||||
& && + \vec{c_1} X^{-1 -N} + \vec{c_2} X^{-2-N} + \cdots + \vec{c_N} X^{-N-N}
|
||||
\end{alignat*}
|
||||
|
||||
$$s(X, Y) = \sum_{i = 1}^N u_i(Y)X^{-i} + \sum_{i = 1}^N v_i(Y) X^i + \sum_{i = 1}^N w_i(Y) X^{i + N}$$
|
||||
\begin{alignat*}{2}
|
||||
s'(X, Y) &= && \; Y^N s(X, Y) - \sum_{i = 1}^N (Y^i + Y^{-i}) X^{i + N} \\
|
||||
&= && \sum_{i = 1}^N X^{-i} Y^N u_i(Y) + \sum_{i = 1}^N X^i Y^N v_i(Y) + \sum_{i = 1}^N X^{i + N} Y^N w_i(Y) - \sum_{i = 1}^N X^{i + N} Y^i - \sum_{i = 1}^N X^{i + N} Y^{-i} \\
|
||||
&= && \; X^{-1} Y^N u_1(Y) + X^{-2} Y^N u_2(Y) + \cdots + X^{-N} Y^N u_N{Y} \\
|
||||
& && + X Y^N v_1(Y) + X^2 Y^N v_2(Y) + \cdots + X^N Y^N v_N(Y) \\
|
||||
& && + X^{N + 1} Y^N w_1(Y) + X^{N + 2} Y^N w_2(Y) + \cdots + X^{N + N} w_N(Y) \\
|
||||
&= && \; X^{-1} (Y^{1 + N} u_{1,1} + \cdots + Y^{Q + N} u_{Q,1}) \\
|
||||
& && + X^{-2} (Y^{1 + N} u_{1,2} + \cdots + Y^{Q + N} u_{Q,2}) \\
|
||||
& && + \cdots \\
|
||||
& && + X^{-N} (Y^{1 + N} u_{1,N} + \cdots + Y^{Q + N} u_{Q,N}) \\
|
||||
& && + X (Y^{1 + N} v_{1,1} + \cdots + Y^{Q + N} v_{Q,1}) \\
|
||||
& && + X^2 (Y^{1 + N} v_{1,2} + \cdots + Y^{Q + N} v_{Q,2}) \\
|
||||
& && + \cdots \\
|
||||
& && + X^N (Y^{1 + N} v_{1,N} + \cdots + Y^{Q + N} v_{Q,N}) \\
|
||||
& && + X^{N + 1} (Y^{1 + N} w_{1,1} + \cdots + Y^{Q + N} w_{Q,1}) \\
|
||||
& && + X^{N + 2} (Y^{1 + N} w_{1,2} + \cdots + Y^{Q + N} w_{Q,2}) \\
|
||||
& && + \cdots \\
|
||||
& && + X^{N + N} (Y^{1 + N} w_{1,N} + \cdots + Y^{Q + N} w_{Q,N}) \\
|
||||
& && - X^{1 + N} Y - X^{1 + N} Y^{-1} \\
|
||||
& && - X^{2 + N} Y^2 - X^{2 + N} Y^{-2} \\
|
||||
& && + \cdots \\
|
||||
& && - X^{N + N} Y^N - X^{N + N} Y^{-N}
|
||||
\end{alignat*}
|
||||
|
||||
The last expansion above is not necessary for the rest of our argument and is simply included for completeness.
|
||||
|
||||
First we compute $r(X, 1) r(X, Y)$ and then $r(X, 1) s'(X, Y)$ to show that the constant argument of $t(X, Y)$ is the left hand side of the combined constraints equation.
|
||||
|
||||
We focus only on expanding the terms where powers of $X$ cancel to $0$.
|
||||
|
||||
\begin{alignat*}{2}
|
||||
r(X, 1) r(X, Y) &= && \cdots + \vec{a_1} X \vec{b_1} X^{-1} Y^{-1} + \cdots + \vec{a_2} X^2 \vec{b_2} X^{-2} Y^{-2} + \cdots + \vec{a_N} X^N \vec{b_N} X^{-N} Y^{-N} + \cdots \\
|
||||
& && + \vec{b_1} X^{-1} \vec{a_1} XY + \cdots + \vec{b_2} X^{-2} \vec{a_2} X^2 Y^2 + \cdots + \vec{b_N} X^{-N} \vec{a_N} X^N Y^N + \cdots \\
|
||||
&= && \; \cdots + \vec{a_1} \vec{b_1} Y^{-1} + \vec{a_2} \vec{b_2} Y^{-2} + \cdots + \vec{a_N} \vec{b_N} Y^{-N} + \vec{a_1} \vec{b_1} Y + \vec{a_2} \vec{b_2} Y^2 + \cdots + \vec{a_N} \vec{b_N} Y^N \\
|
||||
&= && \; \sum_{i = 1}^N \vec{a}_i \vec{b}_i (Y_i + Y^{-i})
|
||||
\end{alignat*}
|
||||
|
||||
\begin{alignat*}{2}
|
||||
r(X, 1) s'(X, Y) &= && \; \vec{a_1} X X^{-1} Y^N u_1(Y) + \vec{a_2} X^2 X^{-2} Y^N u_2(Y) + \cdots + \vec{a_N} X^N X^{-N} Y^N u_N(Y) \\
|
||||
& && + \vec{b_1} X^{-1} X Y^N v_1(Y) + \vec{b_2} X^{-2} X^2 Y^N v_2(Y) + \cdots + \vec{b_N} X^{-N} X^N Y^N v_N(Y) \\
|
||||
& && + \vec{c_1} X^{-1-N} X^{N+1} Y^N w_1(Y) + \vec{c_2} X^{-2 - N} X^{N + 2} Y^N w_2(Y) + \cdots + \vec{c_N} X^{-N-N} X^{N + N} Y^N w_N(Y) \\
|
||||
& && + \vec{c_1} X^{-1-N} (-X^{1 + N} Y - X^{1 + N} Y^{-1}) \\
|
||||
& && + \vec{c_2} X^{-2-N} (-X^{2+N}Y^2 - X^{2+N}Y^{-2}) \\
|
||||
& && + \cdots + \vec{c_N} X^{-N-N} (-X^{N+N} Y^N - X^{N+N} Y^{-N}) \\
|
||||
& && + \cdots \\
|
||||
&= && \; \vec{a_1} Y^N u_1(Y) + \vec{a_2} Y^N u_2(Y) + \cdots + \vec{a_N} Y^N u_N(Y) \\
|
||||
& && + \vec{b_1} Y^N v_1(Y) + \vec{b_2} Y^N v_2(Y) + \cdots + \vec{b_N} Y^N v_N(Y) \\
|
||||
& && + \vec{c_1} Y^N w_1(Y) + \vec{c_2} Y^N w_2(Y) + \cdots + \vec{c_N} Y^N w_N(Y) \\
|
||||
& && + \vec{c_1} (-Y - Y^{-1}) + \vec{c_2} (-Y^2 - Y^{-2}) + \cdots + \vec{c_N} (-Y^N - Y^{-N}) \\
|
||||
& && + \cdots \\
|
||||
&= && \; \sum_{i = 1}^N \vec{a_i} \cdot Y^N u_i(Y) + \sum_{i = 1}^N \vec{b_i} \cdot Y^N v_i(Y) + \sum_{i = 1}^N \vec{c_i} \cdot (Y^N w_i(Y) - Y^i - Y^{-i})
|
||||
\end{alignat*}
|
||||
|
||||
# Simplified Example
|
||||
|
||||
Let $x = 4, y = 6$ then $xy = 24$, and $\vec{a} = (4), \vec{b} = (6), \vec{c} = (24)$ with no linear constraints (all selectors set to zero).
|
||||
|
||||
$$r(X, Y) = 4XY + 6X^{-1}Y^{-1} + 24 X^{-2} Y^{-2}$$
|
||||
$$t(X, Y) = r(X, 1) r(X, Y) - X^{N + 1} Y - X^{N + 1} Y^{-1}$$
|
||||
$$r(X, 1) = 4X + 6X^{-1} + 24 X^{-2}$$
|
||||
\begin{alignat*}{2}
|
||||
r(X, 1) r(X, Y) &= && \; 4X (4XY + 6X^{-1}Y^{-1} + 24 X^{-2} Y^{-2}) \\
|
||||
& && + 6X^{-1} (4XY + 6X^{-1}Y^{-1} + 24 X^{-2} Y^{-2}) \\
|
||||
& && + 24X^{-2} (4XY + 6X^{-1}Y^{-1} + 24 X^{-2} Y^{-2}) \\
|
||||
&= && \; 16X^2 Y + 24 Y^{-1} + 96 X^{-1} Y^{-2} \\
|
||||
& && + 24Y + 36 X^{-2} Y^{-1} + 144 X^{-3} Y^{-2} \\
|
||||
& && + 96 X^{-1} Y + 144 X^{-3} Y^{-1} + 576 X^{-4} Y^{-2} \\
|
||||
r(X, 1) (- X^{N + 1} Y - X^{N + 1} Y^{-1}) &= && \; 4X (- X^{N + 1} Y - X^{N + 1} Y^{-1}) \\
|
||||
& && + 6X^{-1} (- X^{N + 1} Y - X^{N + 1} Y^{-1}) \\
|
||||
& && + 24 X^{-2} (- X^{N + 1} Y - X^{N + 1} Y^{-1}) \\
|
||||
&= && \; - 4X^{N + 2} Y - 4X^{N + 2} Y^{-1}) \\
|
||||
& && - 6X^N Y - 6X^N Y^{-1} \\
|
||||
& && - 24 X^{N - 1} Y - 24 X^{N - 1} Y^{-1}) \\
|
||||
&= && \; - 4X^3 Y - 4X^3 Y^{-1}) \\
|
||||
& && - 6X Y - 6X Y^{-1} \\
|
||||
& && - 24 Y - 24 Y^{-1} \\
|
||||
\end{alignat*}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
```python
|
||||
sage: x
|
||||
x
|
||||
sage: l_2 = (x - 1)*(x - 3)*(x - 4)
|
||||
sage: l_2
|
||||
(x - 1)*(x - 3)*(x - 4)
|
||||
sage: l_2(1)
|
||||
0
|
||||
sage: l_2(3)
|
||||
0
|
||||
sage: l_2(4)
|
||||
0
|
||||
sage: l_2(2)
|
||||
2
|
||||
sage: l_2
|
||||
(x - 1)*(x - 3)*(x - 4)
|
||||
sage: l_2 /= (2-1)*(2-3)*(2-4)
|
||||
sage: l_2(2)
|
||||
1
|
||||
sage: l_3 = (x - 1)*(x - 2)*(x-4) / ((3-1)*(3-2)*(3-4))
|
||||
sage: l_3(1)
|
||||
0
|
||||
sage: l_3(2)
|
||||
0
|
||||
sage: l_3(3)
|
||||
1
|
||||
sage: l_3(4)
|
||||
0
|
||||
sage: l_1 = (x - 2)*(x - 3)*(x - 4) / ((1 - 2)*(1 - 3)*(1
|
||||
....: - 4))
|
||||
sage: l_1(1)
|
||||
1
|
||||
sage: l_1(2)
|
||||
0
|
||||
sage: l_1(3)
|
||||
0
|
||||
sage: l_1(4)
|
||||
0
|
||||
sage: l_1
|
||||
-1/6*(x - 2)*(x - 3)*(x - 4)
|
||||
sage: l_2
|
||||
1/2*(x - 1)*(x - 3)*(x - 4)
|
||||
sage: l_3
|
||||
-1/2*(x - 1)*(x - 2)*(x - 4)
|
||||
sage: l_4
|
||||
----------------------------------------------------------
|
||||
NameError Traceback (most recent call last)
|
||||
<ipython-input-24-cbdd82c87bb0> in <module>
|
||||
----> 1 l_4
|
||||
|
||||
NameError: name 'l_4' is not defined
|
||||
sage: l_4 = (x - 1)*(x - 2)*(x - 3) / ((4 - 1)*(4 - 2)*(4
|
||||
....: - 3))
|
||||
sage: l_4(1)
|
||||
0
|
||||
sage: l_4(2)
|
||||
0
|
||||
sage: l_4(3)
|
||||
0
|
||||
sage: l_4(4)
|
||||
1
|
||||
sage: for i in range(1, 5):
|
||||
....: print(i, l_1(i), l_2(i), l_3(i), l_4(i))
|
||||
....:
|
||||
1 1 0 0 0
|
||||
2 0 1 0 0
|
||||
3 0 0 1 0
|
||||
4 0 0 0 1
|
||||
sage: f = 6 * l_1 + 4 * l_2 + 3 * l_3 + 0 * l_4
|
||||
sage: l_2(2)
|
||||
1
|
||||
sage: for i in range(1, 5):
|
||||
....: print(i, f(i))
|
||||
....:
|
||||
1 6
|
||||
2 4
|
||||
3 3
|
||||
4 0
|
||||
```
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
param public_u
|
||||
param public_v
|
||||
param value
|
||||
param serial
|
||||
param randomness_coin
|
||||
param randomness_value
|
||||
constant generator_coin
|
||||
constant generator_value_commit_value
|
||||
constant generator_value_commit_random
|
||||
|
||||
public coin = mimc_hash(public_u, public_v, value, serial, randomness_coin)
|
||||
|
||||
private value_digits = unpack(value)
|
||||
rangeproof_assert(value, value_digits)
|
||||
public value_commit = jj_add(
|
||||
jj_mul(value, generator_value_commit_value),
|
||||
jj_mul(randomness_value, generator_value_commit_random)
|
||||
)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
param value
|
||||
|
||||
private value_bits[] = unpack(value)
|
||||
|
||||
digit = 1
|
||||
linear_combo = []
|
||||
for bit in value_bits:
|
||||
enforce (bit) * (1 - bit) == 0
|
||||
|
||||
linear_combo.append((digit bit))
|
||||
|
||||
digit = digit.double()
|
||||
|
||||
enforce (linear_combo) * (~one) == value
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
param secret
|
||||
param serial
|
||||
param coin_merkle_branch[4]
|
||||
param coin_merkle_is_right[4]
|
||||
constant generator_coin
|
||||
constant generator_value_commit_value
|
||||
constant generator_value_commit_random
|
||||
|
||||
public nullifier = mimc_hash(secret, serial)
|
||||
|
||||
private (public_u, public_v) = jj_mul(secret, generator_coin)
|
||||
public coin = mimc_hash(public_u, public_v, value, serial, randomness_coin)
|
||||
|
||||
let current = coin
|
||||
for i in range(4):
|
||||
branch = coin_merkle_branch[i]
|
||||
is_right = coin_merkle_is_right[i]
|
||||
|
||||
# reverse(a, b, condition) = if condition (b, a) else (a, b)
|
||||
private left, right = conditionally_reverse(current, branch, is_right)
|
||||
|
||||
# Only the last one is public
|
||||
if i == 3:
|
||||
current = public mimc_hash(left, right)
|
||||
else:
|
||||
current = private mimc_hash(left, right)
|
||||
|
||||
private value_digits = unpack(value)
|
||||
rangeproof_assert(value, value_digits)
|
||||
public value_commit = jj_add(
|
||||
jj_mul(value, generator_value_commit_value),
|
||||
jj_mul(randomness_value, generator_value_commit_random)
|
||||
)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
We have a vanishing polynomial $Z(X) = X^N - 1$. Implicitly we are proving that
|
||||
|
||||
$$X^N = 1$$
|
||||
|
||||
What are the solutions to this polynomial? Well the answer is $\omega$ which is any root of $1$.
|
||||
|
||||
Therefore the solution to the formula $X^N - 1$ will be all the values of $X^N = 1$ or
|
||||
|
||||
$$X^N - 1 = (\omega - 1)(\omega^2 - 1)\cdots(\omega^{N - 1} - 1)$$
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
accept_url = "127.0.0.1:7777"
|
||||
rpc_url = "http://127.0.0.1:8000"
|
||||
client_database_path = "cashier_client_database.db"
|
||||
btc_endpoint = "tcp://electrum.blockstream.info:50001"
|
||||
gateway_url = "127.0.0.1:3333"
|
||||
log_path = "/tmp/cashierd.log"
|
||||
cashierdb_path = "~/.config/darkfi/cashier.db"
|
||||
client_walletdb_path = "~/.config/darkfi/cashier_client_walletdb.db"
|
||||
password = "TEST_PASSWORD"
|
||||
client_password = "TEST_PASSWORD"
|
||||
@@ -1,8 +0,0 @@
|
||||
connect_url = "127.0.0.1:3333"
|
||||
subscriber_url = "127.0.0.1:4444"
|
||||
cashier_url = "127.0.0.1:7777"
|
||||
rpc_url = "127.0.0.1:8000"
|
||||
database_path = "~/.config/darkfi/database_client.db"
|
||||
walletdb_path = "~/.config/darkfi/walletdb.db"
|
||||
log_path = "/tmp/darkfid_service_daemon.log"
|
||||
password = "TEST_PASSWORD"
|
||||
@@ -1,2 +0,0 @@
|
||||
rpc_url = "http://127.0.0.1:8000"
|
||||
log_path = "/tmp/drk_cli.log"
|
||||
@@ -1,4 +0,0 @@
|
||||
connect_url = "127.0.0.1:3333"
|
||||
publisher_url = "127.0.0.1:4444"
|
||||
database_path = "gatewayd.db"
|
||||
log_path = "/tmp/gatewayd.log"
|
||||
791
examples/halo2/Cargo.lock
generated
791
examples/halo2/Cargo.lock
generated
@@ -1,791 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
|
||||
dependencies = [
|
||||
"aes-soft",
|
||||
"aesni",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-soft"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aesni"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bigint"
|
||||
version = "4.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec 0.5.2",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-modes"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
|
||||
|
||||
[[package]]
|
||||
name = "bls12_381"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
|
||||
[[package]]
|
||||
name = "crypto_api"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f855e87e75a4799e18b8529178adcde6fd4f97c1449ff4821e747ff728bb102"
|
||||
|
||||
[[package]]
|
||||
name = "crypto_api_chachapoly"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d930b6a026ce9d358a17f9c9046c55d90b14bb847f36b6ebb6b19365d4feffb8"
|
||||
dependencies = [
|
||||
"crypto_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fpe"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a25080721bbcd2cd4d765b7d607ea350425fa087ce53cd3e31afcacdab850352"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"block-modes",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"ff",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halo2"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/zcash/halo2.git?rev=27c4187673a9c6ade13fbdbd4f20955530c22d7f#27c4187673a9c6ade13fbdbd4f20955530c22d7f"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"ff",
|
||||
"group",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halo2_ecc"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.1",
|
||||
"bigint",
|
||||
"ff",
|
||||
"group",
|
||||
"halo2",
|
||||
"halo2_utilities",
|
||||
"lazy_static",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halo2_examples"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.1",
|
||||
"bigint",
|
||||
"bitvec",
|
||||
"ff",
|
||||
"group",
|
||||
"halo2",
|
||||
"halo2_ecc",
|
||||
"halo2_poseidon",
|
||||
"halo2_utilities",
|
||||
"lazy_static",
|
||||
"orchard",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
"sinsemilla",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halo2_poseidon"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"ff",
|
||||
"halo2",
|
||||
"halo2_utilities",
|
||||
"pasta_curves",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halo2_utilities"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
dependencies = [
|
||||
"bigint",
|
||||
"ff",
|
||||
"halo2",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "incrementalmerkletree"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16d75fb342984cc8cea665a9ef5607b4956569839ca098172082fa1b19bdaf02"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jubjub"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "593fc4726ca80edb47ee18ab4d826719e25c2096991a79308b44fb915c6014ef"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bls12_381",
|
||||
"ff",
|
||||
"group",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nonempty"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "orchard"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arrayvec 0.7.1",
|
||||
"bigint",
|
||||
"bitvec",
|
||||
"blake2b_simd",
|
||||
"ff",
|
||||
"fpe",
|
||||
"group",
|
||||
"halo2",
|
||||
"halo2_ecc",
|
||||
"halo2_poseidon",
|
||||
"halo2_utilities",
|
||||
"incrementalmerkletree",
|
||||
"lazy_static",
|
||||
"nonempty",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
"reddsa",
|
||||
"serde",
|
||||
"sinsemilla",
|
||||
"subtle",
|
||||
"zcash_note_encryption",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pasta_curves"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a21914ddc589b74e7638091c8e91a4e8b083ee5e1d0066d64407131b7570799"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"ff",
|
||||
"group",
|
||||
"lazy_static",
|
||||
"rand",
|
||||
"static_assertions",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reddsa"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/str4d/redjubjub.git?rev=d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2#d5d8c5f3bb704bad8ae88fe4a29ae1f744774cb2"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
"digest",
|
||||
"group",
|
||||
"jubjub",
|
||||
"pasta_curves",
|
||||
"rand_core",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sinsemilla"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/parazyd/orchard.git?rev=f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9#f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"group",
|
||||
"halo2",
|
||||
"halo2_ecc",
|
||||
"halo2_utilities",
|
||||
"pasta_curves",
|
||||
"rand",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zcash_note_encryption"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=13b023387bafdc7b5712c933dc0e16ee94b96a6a#13b023387bafdc7b5712c933dc0e16ee94b96a6a"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
"crypto_api_chachapoly",
|
||||
"ff",
|
||||
"group",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
@@ -1,47 +0,0 @@
|
||||
[package]
|
||||
name = "halo2_examples"
|
||||
version = "0.1.0"
|
||||
authors = ["narodnik <x@x.org>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ff = "0.10"
|
||||
group = "0.10"
|
||||
pasta_curves = "0.1.2"
|
||||
bitvec = "0.22"
|
||||
rand = "0.8.4"
|
||||
arrayvec = "0.7.0"
|
||||
lazy_static = "1"
|
||||
bigint = "4"
|
||||
subtle = "2.3"
|
||||
halo2 = "0.0"
|
||||
|
||||
[patch.crates-io]
|
||||
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" }
|
||||
|
||||
[dependencies.halo2_poseidon]
|
||||
git = "https://github.com/parazyd/orchard.git"
|
||||
#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
|
||||
rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
features = ["halo2"]
|
||||
|
||||
[dependencies.halo2_utilities]
|
||||
git = "https://github.com/parazyd/orchard.git"
|
||||
#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
|
||||
rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
|
||||
[dependencies.halo2_ecc]
|
||||
git = "https://github.com/parazyd/orchard.git"
|
||||
#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
|
||||
rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
|
||||
[dependencies.sinsemilla]
|
||||
git = "https://github.com/parazyd/orchard.git"
|
||||
#rev = "0d14f2390734e4710fc24a976f037dae3a6e7ac8"
|
||||
rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
|
||||
[dependencies.orchard]
|
||||
git = "https://github.com/parazyd/orchard.git"
|
||||
rev = "f9cc01c21010b31988129f9cbc2ca8c0bdbf2ee9"
|
||||
@@ -1,6 +0,0 @@
|
||||
Always use the --release flag otherwise it's too slow:
|
||||
|
||||
```
|
||||
cargo run --release --bin simple3
|
||||
```
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
use std::iter;
|
||||
|
||||
use group::{ff::PrimeFieldBits, Curve};
|
||||
use halo2::{
|
||||
arithmetic::{CurveAffine, Field, FieldExt},
|
||||
pasta::{Fp, Fq},
|
||||
};
|
||||
use halo2_ecc::gadget::FixedPoints;
|
||||
use halo2_poseidon::primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier};
|
||||
use orchard::constants::{fixed_bases::OrchardFixedBases, sinsemilla::MERKLE_CRH_PERSONALIZATION};
|
||||
use rand::rngs::OsRng;
|
||||
use sinsemilla::primitive::{CommitDomain, HashDomain};
|
||||
|
||||
use halo2_examples::pedersen_commitment;
|
||||
|
||||
fn main() {
|
||||
let secret_key = Fq::random(&mut OsRng);
|
||||
let serial = Fp::random(&mut OsRng);
|
||||
|
||||
// Sinsemilla hash
|
||||
let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
|
||||
let nullifier = domain
|
||||
.hash(
|
||||
iter::empty()
|
||||
.chain(secret_key.to_le_bits().iter().by_val())
|
||||
.chain(serial.to_le_bits().iter().by_val()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let public_key = OrchardFixedBases::SpendAuthG.generator() * secret_key;
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
|
||||
let value = 110;
|
||||
let asset = 1;
|
||||
|
||||
let value_blind = Fq::random(&mut OsRng);
|
||||
let asset_blind = Fq::random(&mut OsRng);
|
||||
|
||||
let coin_blind = Fp::random(&mut OsRng);
|
||||
|
||||
// FIXME:
|
||||
let messages = [
|
||||
[*coords.x(), *coords.y()],
|
||||
[Fp::from(value), Fp::from(asset)],
|
||||
[serial, coin_blind],
|
||||
];
|
||||
let mut coin = Fp::zero();
|
||||
for msg in messages.iter() {
|
||||
coin += Hash::init(OrchardNullifier, ConstantLength::<2>).hash(*msg);
|
||||
}
|
||||
|
||||
// TODO: Merkle
|
||||
|
||||
let value_commit = pedersen_commitment(value, value_blind);
|
||||
let asset_commit = pedersen_commitment(asset, asset_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
let asset_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let sig_secret = Fq::random(&mut OsRng);
|
||||
let sig_pubkey = OrchardFixedBases::SpendAuthG.generator() * sig_secret;
|
||||
let sig_pk_coords = sig_pubkey.to_affine().coordinates().unwrap();
|
||||
|
||||
let mut public_inputs = vec![
|
||||
nullifier,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*asset_coords.x(),
|
||||
*asset_coords.y(),
|
||||
// merkle_root,
|
||||
*sig_pk_coords.x(),
|
||||
*sig_pk_coords.y(),
|
||||
];
|
||||
}
|
||||
@@ -1,439 +0,0 @@
|
||||
use std::{convert::TryInto, time::Instant};
|
||||
|
||||
use group::{ff::Field, Curve, Group};
|
||||
use halo2::{
|
||||
arithmetic::CurveAffine,
|
||||
circuit::{floor_planner, Layouter},
|
||||
dev::MockProver,
|
||||
pasta::{vesta, Ep, Fp, Fq},
|
||||
plonk,
|
||||
plonk::{Circuit, ConstraintSystem, Error},
|
||||
poly::commitment,
|
||||
transcript::{Blake2bRead, Blake2bWrite},
|
||||
};
|
||||
use halo2_ecc::{chip::EccChip, gadget::FixedPoint};
|
||||
use halo2_poseidon::{
|
||||
gadget::{Hash as PoseidonHash, Word},
|
||||
pow5t3::{Pow5T3Chip as PoseidonChip, StateWord},
|
||||
primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier},
|
||||
};
|
||||
use halo2_utilities::{
|
||||
lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
|
||||
};
|
||||
use orchard::constants::fixed_bases::OrchardFixedBases;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use halo2_examples::{circuit::Config, pedersen_commitment};
|
||||
|
||||
const K: u32 = 9;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct MintCircuit {
|
||||
pub_x: Option<Fp>, // x coordinate for pubkey
|
||||
pub_y: Option<Fp>, // y coordinate for pubkey
|
||||
value: Option<Fp>, // The value of this coin
|
||||
asset: Option<Fp>, // The asset ID
|
||||
serial: Option<Fp>, // Unique serial number corresponding to this coin
|
||||
coin_blind: Option<Fp>, // Random blinding factor for coin
|
||||
value_blind: Option<Fq>, // Random blinding factor for value commitment
|
||||
asset_blind: Option<Fq>, // Random blinding factor for the asset ID
|
||||
}
|
||||
|
||||
impl UtilitiesInstructions<Fp> for MintCircuit {
|
||||
type Var = CellValue<Fp>;
|
||||
}
|
||||
|
||||
impl Circuit<Fp> for MintCircuit {
|
||||
type Config = Config;
|
||||
type FloorPlanner = floor_planner::V1;
|
||||
//type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
|
||||
let advices = [
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
];
|
||||
|
||||
let q_add = meta.selector();
|
||||
|
||||
let table_idx = meta.lookup_table_column();
|
||||
|
||||
// let lookup = (
|
||||
// table_idx,
|
||||
// meta.lookup_table_column(),
|
||||
// meta.lookup_table_column(),
|
||||
// );
|
||||
|
||||
let primary = meta.instance_column();
|
||||
|
||||
meta.enable_equality(primary.into());
|
||||
|
||||
for advice in advices.iter() {
|
||||
meta.enable_equality((*advice).into());
|
||||
}
|
||||
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
|
||||
let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
|
||||
|
||||
meta.enable_constant(lagrange_coeffs[0]);
|
||||
|
||||
let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
|
||||
|
||||
let ecc_config = EccChip::<OrchardFixedBases>::configure(
|
||||
meta,
|
||||
advices,
|
||||
lagrange_coeffs,
|
||||
range_check.clone(),
|
||||
);
|
||||
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
meta,
|
||||
OrchardNullifier,
|
||||
advices[6..9].try_into().unwrap(),
|
||||
advices[5],
|
||||
rc_a,
|
||||
rc_b,
|
||||
);
|
||||
|
||||
Config {
|
||||
primary,
|
||||
q_add,
|
||||
advices,
|
||||
ecc_config,
|
||||
poseidon_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<Fp>,
|
||||
) -> Result<(), Error> {
|
||||
// Construct the ECC chip.
|
||||
let ecc_chip = EccChip::construct(config.ecc_config.clone());
|
||||
|
||||
let pub_x = self.load_private(
|
||||
layouter.namespace(|| "load pubkey x"),
|
||||
config.advices[0],
|
||||
self.pub_x,
|
||||
)?;
|
||||
let pub_y = self.load_private(
|
||||
layouter.namespace(|| "load pubkey y"),
|
||||
config.advices[0],
|
||||
self.pub_y,
|
||||
)?;
|
||||
let value = self.load_private(
|
||||
layouter.namespace(|| "load value"),
|
||||
config.advices[0],
|
||||
self.value,
|
||||
)?;
|
||||
let asset = self.load_private(
|
||||
layouter.namespace(|| "load asset"),
|
||||
config.advices[0],
|
||||
self.asset,
|
||||
)?;
|
||||
let serial = self.load_private(
|
||||
layouter.namespace(|| "load serial"),
|
||||
config.advices[0],
|
||||
self.serial,
|
||||
)?;
|
||||
let coin_blind = self.load_private(
|
||||
layouter.namespace(|| "load coin_blind"),
|
||||
config.advices[0],
|
||||
self.coin_blind,
|
||||
)?;
|
||||
|
||||
// =============
|
||||
// = Coin hash =
|
||||
// =============
|
||||
|
||||
// TODO: This is a hack until issue is resolved in poseidon gadget
|
||||
let mut coin = Fp::zero();
|
||||
let messages = [[pub_x, pub_y], [value, asset], [serial, coin_blind]];
|
||||
//let messages = [[pub_x, pub_y], [value, asset]];
|
||||
//let messages = [[pub_x, pub_y]];
|
||||
for msg in messages.iter() {
|
||||
let poseidon_message = layouter.assign_region(
|
||||
|| "load message",
|
||||
|mut region| {
|
||||
let mut message_word = |i: usize| {
|
||||
let val = msg[i].value();
|
||||
let var = region.assign_advice(
|
||||
|| format!("load message_{}", i),
|
||||
config.poseidon_config.state()[i],
|
||||
0,
|
||||
|| val.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(var, msg[i].cell())?;
|
||||
Ok(Word::<_, _, OrchardNullifier, 3, 2>::from_inner(
|
||||
StateWord::new(var, val),
|
||||
))
|
||||
};
|
||||
Ok([message_word(0)?, message_word(1)?])
|
||||
},
|
||||
)?;
|
||||
|
||||
let poseidon_hasher = PoseidonHash::init(
|
||||
PoseidonChip::construct(config.poseidon_config.clone()),
|
||||
layouter.namespace(|| "Poseidon init"),
|
||||
ConstantLength::<2>,
|
||||
)?;
|
||||
|
||||
let poseidon_output =
|
||||
poseidon_hasher.hash(layouter.namespace(|| "Poseidon hash"), poseidon_message)?;
|
||||
|
||||
let poseidon_output: CellValue<Fp> = poseidon_output.inner().into();
|
||||
|
||||
if !poseidon_output.value().is_none() {
|
||||
coin += poseidon_output.value().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// if coin != Fp::zero() {
|
||||
// println!("circuit hash: {:?}", coin);
|
||||
// }
|
||||
|
||||
let hash = self.load_private(
|
||||
layouter.namespace(|| "load hash"),
|
||||
config.advices[0],
|
||||
Some(coin),
|
||||
)?;
|
||||
|
||||
// Constrain the coin C; index in public values is 0
|
||||
layouter.constrain_instance(hash.cell(), config.primary, 0)?;
|
||||
|
||||
// ====================
|
||||
// = Value commitment =
|
||||
// ====================
|
||||
|
||||
// This constant one is used for multiplication
|
||||
let one = self.load_constant(
|
||||
layouter.namespace(|| "constant one"),
|
||||
config.advices[0],
|
||||
Fp::one(),
|
||||
)?;
|
||||
|
||||
// v*G_1
|
||||
let (commitment, _) = {
|
||||
let value_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), value_commit_v);
|
||||
value_commit_v.mul_short(layouter.namespace(|| "[value] ValueCommitV"), (value, one))?
|
||||
};
|
||||
|
||||
// r_V*G_2
|
||||
let (blind, _rcv) = {
|
||||
let rcv = self.value_blind;
|
||||
let value_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), value_commit_r);
|
||||
value_commit_r.mul(layouter.namespace(|| "[value_blind] ValueCommitR"), rcv)?
|
||||
};
|
||||
|
||||
// Constrain the x and y; indexes in public values are 1 and 2
|
||||
let value_commit = commitment.add(layouter.namespace(|| "valuecommit"), &blind)?;
|
||||
layouter.constrain_instance(value_commit.inner().x().cell(), config.primary, 1)?;
|
||||
layouter.constrain_instance(value_commit.inner().y().cell(), config.primary, 2)?;
|
||||
|
||||
// ====================
|
||||
// = Asset commitment =
|
||||
// ====================
|
||||
|
||||
// a*G_1
|
||||
let (commitment, _) = {
|
||||
let asset_commit_v = OrchardFixedBases::ValueCommitV;
|
||||
let asset_commit_v = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_v);
|
||||
asset_commit_v.mul_short(layouter.namespace(|| "[asset] ValueCommitV"), (asset, one))?
|
||||
};
|
||||
|
||||
// r_A*G_2
|
||||
let (blind, _rca) = {
|
||||
let rca = self.asset_blind;
|
||||
let asset_commit_r = OrchardFixedBases::ValueCommitR;
|
||||
let asset_commit_r = FixedPoint::from_inner(ecc_chip.clone(), asset_commit_r);
|
||||
asset_commit_r.mul(layouter.namespace(|| "[asset_blind] ValueCommitR"), rca)?
|
||||
};
|
||||
|
||||
// Constrain the x and y; indexes in public values are 3 and 4
|
||||
let asset_commit = commitment.add(layouter.namespace(|| "assetcommit"), &blind)?;
|
||||
layouter.constrain_instance(asset_commit.inner().x().cell(), config.primary, 3)?;
|
||||
layouter.constrain_instance(asset_commit.inner().y().cell(), config.primary, 4)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VerifyingKey {
|
||||
params: commitment::Params<vesta::Affine>,
|
||||
vk: plonk::VerifyingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl VerifyingKey {
|
||||
fn build() -> Self {
|
||||
let params = commitment::Params::new(K);
|
||||
let circuit: MintCircuit = Default::default();
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
|
||||
VerifyingKey { params, vk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProvingKey {
|
||||
params: commitment::Params<vesta::Affine>,
|
||||
pk: plonk::ProvingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl ProvingKey {
|
||||
fn build() -> Self {
|
||||
let params = commitment::Params::new(K);
|
||||
let circuit: MintCircuit = Default::default();
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, &circuit).unwrap();
|
||||
|
||||
ProvingKey { params, pk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Proof(Vec<u8>);
|
||||
|
||||
impl AsRef<[u8]> for Proof {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Proof {
|
||||
fn create(pk: &ProvingKey, circuits: &[MintCircuit], pubinputs: &[Fp]) -> Result<Self, Error> {
|
||||
let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
|
||||
plonk::create_proof(
|
||||
&pk.params,
|
||||
&pk.pk,
|
||||
circuits,
|
||||
&[&[pubinputs]],
|
||||
&mut transcript,
|
||||
)?;
|
||||
Ok(Proof(transcript.finalize()))
|
||||
}
|
||||
|
||||
fn verify(&self, vk: &VerifyingKey, pubinputs: &[Fp]) -> Result<(), plonk::Error> {
|
||||
let msm = vk.params.empty_msm();
|
||||
let mut transcript = Blake2bRead::init(&self.0[..]);
|
||||
let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &[&[pubinputs]], &mut transcript)?;
|
||||
let msm = guard.clone().use_challenges();
|
||||
if msm.eval() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ConstraintSystemFailure)
|
||||
}
|
||||
}
|
||||
|
||||
// fn new(bytes: Vec<u8>) -> Self {
|
||||
// Proof(bytes)
|
||||
// }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let pubkey = Ep::random(&mut OsRng);
|
||||
let coords = pubkey.to_affine().coordinates().unwrap();
|
||||
|
||||
let value = 110;
|
||||
let asset = 1;
|
||||
|
||||
let value_blind = Fq::random(&mut OsRng);
|
||||
let asset_blind = Fq::random(&mut OsRng);
|
||||
|
||||
let serial = Fp::random(&mut OsRng);
|
||||
let coin_blind = Fp::random(&mut OsRng);
|
||||
|
||||
let mut coin = Fp::zero();
|
||||
|
||||
let messages = [
|
||||
[*coords.x(), *coords.y()],
|
||||
[Fp::from(value), Fp::from(asset)],
|
||||
[serial, coin_blind],
|
||||
];
|
||||
|
||||
// TODO: This is a hack until issue is fixed in poseidon gadget
|
||||
for msg in messages.iter() {
|
||||
coin += Hash::init(OrchardNullifier, ConstantLength::<2>).hash(*msg);
|
||||
}
|
||||
|
||||
let value_commit = pedersen_commitment(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let asset_commit = pedersen_commitment(asset, asset_blind);
|
||||
let asset_coords = asset_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let mut public_inputs = vec![
|
||||
coin,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*asset_coords.x(),
|
||||
*asset_coords.y(),
|
||||
];
|
||||
|
||||
let circuit = MintCircuit {
|
||||
pub_x: Some(*coords.x()),
|
||||
pub_y: Some(*coords.y()),
|
||||
value: Some(vesta::Scalar::from(value)),
|
||||
asset: Some(vesta::Scalar::from(asset)),
|
||||
serial: Some(serial),
|
||||
coin_blind: Some(coin_blind),
|
||||
value_blind: Some(value_blind),
|
||||
asset_blind: Some(asset_blind),
|
||||
};
|
||||
|
||||
// Valid MockProver
|
||||
let prover = MockProver::run(K, &circuit, vec![public_inputs.clone()]).unwrap();
|
||||
assert_eq!(prover.verify(), Ok(()));
|
||||
|
||||
// Add 1 to break the public inputs
|
||||
public_inputs[0] += Fp::from(0xdeadbeef);
|
||||
|
||||
// Invalid MockProver
|
||||
let prover = MockProver::run(K, &circuit, vec![public_inputs.clone()]).unwrap();
|
||||
assert!(prover.verify().is_err());
|
||||
|
||||
// Remove 1 to make the public inputs valid again
|
||||
public_inputs[0] -= Fp::from(0xdeadbeef);
|
||||
|
||||
// Actual ZK proof
|
||||
let start = Instant::now();
|
||||
let vk = VerifyingKey::build();
|
||||
let pk = ProvingKey::build();
|
||||
println!("\nSetup: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();
|
||||
println!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
assert!(proof.verify(&vk, &public_inputs).is_ok());
|
||||
println!("Verify: [{:?}]", start.elapsed());
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
use std::convert::TryInto;
|
||||
use std::time::Instant;
|
||||
|
||||
use halo2::{
|
||||
circuit::{floor_planner, Layouter},
|
||||
pasta::{vesta, Fp},
|
||||
plonk,
|
||||
plonk::{
|
||||
Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
|
||||
},
|
||||
poly::{commitment, Rotation},
|
||||
transcript::{Blake2bRead, Blake2bWrite},
|
||||
};
|
||||
|
||||
use halo2_poseidon::{
|
||||
gadget::{Hash as PoseidonHash, Word},
|
||||
pow5t3::{Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig, StateWord},
|
||||
primitive::{ConstantLength, Hash, P128Pow5T3 as OrchardNullifier},
|
||||
};
|
||||
use halo2_utilities::{copy, CellValue, UtilitiesInstructions, Var};
|
||||
|
||||
const K: u32 = 6;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Config {
|
||||
primary: Column<InstanceColumn>,
|
||||
q_add: Selector,
|
||||
advices: [Column<Advice>; 10],
|
||||
poseidon_config: PoseidonConfig<Fp>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct HashCircuit {
|
||||
a: Option<Fp>, // First input for hash
|
||||
b: Option<Fp>, // Second input for hash
|
||||
c: Option<Fp>, // c is summed with hash
|
||||
}
|
||||
|
||||
impl UtilitiesInstructions<Fp> for HashCircuit {
|
||||
type Var = CellValue<Fp>;
|
||||
}
|
||||
|
||||
impl Circuit<Fp> for HashCircuit {
|
||||
type Config = Config;
|
||||
type FloorPlanner = floor_planner::V1;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn configure(meta: &mut ConstraintSystem<Fp>) -> Self::Config {
|
||||
// 10 advice columns
|
||||
let advices = [
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
meta.advice_column(),
|
||||
];
|
||||
|
||||
// Addition of two field elements: poseidon_hash(a, b) + c
|
||||
let q_add = meta.selector();
|
||||
|
||||
meta.create_gate("poseidon_hash(a, b) + c", |meta| {
|
||||
let q_add = meta.query_selector(q_add);
|
||||
let sum = meta.query_advice(advices[6], Rotation::cur());
|
||||
let hash = meta.query_advice(advices[7], Rotation::cur());
|
||||
let c = meta.query_advice(advices[8], Rotation::cur());
|
||||
|
||||
vec![q_add * (hash + c - sum)]
|
||||
});
|
||||
|
||||
let primary = meta.instance_column();
|
||||
meta.enable_equality(primary.into());
|
||||
|
||||
for advice in advices.iter() {
|
||||
meta.enable_equality((*advice).into());
|
||||
}
|
||||
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
|
||||
let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
|
||||
|
||||
meta.enable_constant(lagrange_coeffs[0]);
|
||||
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
meta,
|
||||
OrchardNullifier,
|
||||
advices[6..9].try_into().unwrap(),
|
||||
advices[5],
|
||||
rc_a,
|
||||
rc_b,
|
||||
);
|
||||
|
||||
Config {
|
||||
primary,
|
||||
q_add,
|
||||
advices,
|
||||
poseidon_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
config: Self::Config,
|
||||
mut layouter: impl Layouter<Fp>,
|
||||
) -> Result<(), Error> {
|
||||
let a = self.load_private(layouter.namespace(|| "load a"), config.advices[0], self.a)?;
|
||||
let b = self.load_private(layouter.namespace(|| "load b"), config.advices[0], self.b)?;
|
||||
let c = self.load_private(layouter.namespace(|| "load c"), config.advices[0], self.c)?;
|
||||
|
||||
let hash = {
|
||||
let message = [a, b];
|
||||
|
||||
let poseidon_message = layouter.assign_region(
|
||||
|| "load message",
|
||||
|mut region| {
|
||||
let mut message_word = |i: usize| {
|
||||
let value = message[i].value();
|
||||
let var = region.assign_advice(
|
||||
|| format!("load message_{}", i),
|
||||
config.poseidon_config.state()[i],
|
||||
0,
|
||||
|| value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(var, message[i].cell())?;
|
||||
Ok(Word::<_, _, OrchardNullifier, 3, 2>::from_inner(
|
||||
StateWord::new(var, value),
|
||||
))
|
||||
};
|
||||
Ok([message_word(0)?, message_word(1)?])
|
||||
},
|
||||
)?;
|
||||
|
||||
let poseidon_hasher = PoseidonHash::init(
|
||||
//config.poseidon_chip(),
|
||||
PoseidonChip::construct(config.poseidon_config.clone()),
|
||||
layouter.namespace(|| "Poseidon init"),
|
||||
ConstantLength::<2>,
|
||||
)?;
|
||||
|
||||
let poseidon_output = poseidon_hasher.hash(
|
||||
layouter.namespace(|| "Poseidon hash (a, b)"),
|
||||
poseidon_message,
|
||||
)?;
|
||||
|
||||
let poseidon_output: CellValue<Fp> = poseidon_output.inner().into();
|
||||
poseidon_output
|
||||
};
|
||||
|
||||
// Add hash output to c
|
||||
let scalar = layouter.assign_region(
|
||||
|| " `scalar` = poseidon_hash(a, b) + c",
|
||||
|mut region| {
|
||||
config.q_add.enable(&mut region, 0)?;
|
||||
|
||||
copy(&mut region, || "copy hash", config.advices[7], 0, &hash)?;
|
||||
copy(&mut region, || "copy c", config.advices[8], 0, &c)?;
|
||||
|
||||
let scalar_val = hash.value().zip(c.value()).map(|(hash, c)| hash + c);
|
||||
|
||||
let cell = region.assign_advice(
|
||||
|| "poseidon_hash(a, b) + c",
|
||||
config.advices[6],
|
||||
0,
|
||||
|| scalar_val.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
Ok(CellValue::new(cell, scalar_val))
|
||||
},
|
||||
)?;
|
||||
|
||||
layouter.constrain_instance(scalar.cell(), config.primary, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VerifyingKey {
|
||||
params: commitment::Params<vesta::Affine>,
|
||||
vk: plonk::VerifyingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl VerifyingKey {
|
||||
fn build() -> Self {
|
||||
let params = commitment::Params::new(K);
|
||||
let circuit: HashCircuit = Default::default();
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
|
||||
VerifyingKey { params, vk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProvingKey {
|
||||
params: commitment::Params<vesta::Affine>,
|
||||
pk: plonk::ProvingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl ProvingKey {
|
||||
fn build() -> Self {
|
||||
let params = commitment::Params::new(K);
|
||||
let circuit: HashCircuit = Default::default();
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, &circuit).unwrap();
|
||||
|
||||
ProvingKey { params, pk }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Proof(Vec<u8>);
|
||||
|
||||
impl AsRef<[u8]> for Proof {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Proof {
|
||||
fn create(pk: &ProvingKey, circuits: &[HashCircuit], pubinputs: &[Fp]) -> Result<Self, Error> {
|
||||
let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
|
||||
plonk::create_proof(
|
||||
&pk.params,
|
||||
&pk.pk,
|
||||
circuits,
|
||||
&[&[pubinputs]],
|
||||
&mut transcript,
|
||||
)?;
|
||||
Ok(Proof(transcript.finalize()))
|
||||
}
|
||||
|
||||
fn verify(&self, vk: &VerifyingKey, pubinputs: &[Fp]) -> Result<(), plonk::Error> {
|
||||
let msm = vk.params.empty_msm();
|
||||
let mut transcript = Blake2bRead::init(&self.0[..]);
|
||||
let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &[&[pubinputs]], &mut transcript)?;
|
||||
let msm = guard.clone().use_challenges();
|
||||
if msm.eval() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::ConstraintSystemFailure)
|
||||
}
|
||||
}
|
||||
|
||||
// fn new(bytes: Vec<u8>) -> Self {
|
||||
// Proof(bytes)
|
||||
// }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = Fp::from(13);
|
||||
let b = Fp::from(69);
|
||||
let c = Fp::from(42);
|
||||
|
||||
let message = [a, b];
|
||||
let output = Hash::init(OrchardNullifier, ConstantLength::<2>).hash(message);
|
||||
|
||||
let circuit = HashCircuit {
|
||||
a: Some(a),
|
||||
b: Some(b),
|
||||
c: Some(c),
|
||||
};
|
||||
|
||||
let sum = output + c;
|
||||
|
||||
// Correct:
|
||||
let public_inputs = vec![sum];
|
||||
// Incorrect:
|
||||
// let public_inputs = vec![sum + Fp::one()];
|
||||
|
||||
let start = Instant::now();
|
||||
let vk = VerifyingKey::build();
|
||||
let pk = ProvingKey::build();
|
||||
println!("Setup: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();
|
||||
println!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
assert!(proof.verify(&vk, &public_inputs).is_ok());
|
||||
println!("Verify: [{:?}]", start.elapsed());
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
use halo2::{
|
||||
circuit::{SimpleFloorPlanner, Chip, Layouter},
|
||||
pasta::{EqAffine, Fp},
|
||||
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression, Selector, create_proof, verify_proof, keygen_vk, keygen_pk},
|
||||
poly::{commitment::Params, Rotation},
|
||||
transcript::{Blake2bRead, Blake2bWrite, Challenge255},
|
||||
};
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct CoolConfig {
|
||||
a_col: Column<Advice>,
|
||||
s_range: Selector,
|
||||
}
|
||||
|
||||
struct CoolChip {
|
||||
config: CoolConfig
|
||||
}
|
||||
|
||||
impl Chip<Fp> for CoolChip {
|
||||
type Config = CoolConfig;
|
||||
type Loaded = ();
|
||||
|
||||
fn config(&self) -> &Self::Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
fn loaded(&self) -> &Self::Loaded {
|
||||
&()
|
||||
}
|
||||
}
|
||||
|
||||
impl CoolChip {
|
||||
fn construct(config: CoolConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
fn configure(cs: &mut ConstraintSystem<Fp>) -> CoolConfig {
|
||||
let a_col = cs.advice_column();
|
||||
let s_range = cs.selector();
|
||||
|
||||
cs.create_gate("check", |cs| {
|
||||
let a = cs.query_advice(a_col, Rotation::cur());
|
||||
let s_range = cs.query_selector(s_range);
|
||||
vec![s_range * (a - Expression::Constant(Fp::from(2)))]
|
||||
});
|
||||
|
||||
CoolConfig { a_col, s_range }
|
||||
}
|
||||
|
||||
fn alloc_and_check(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<Fp>,
|
||||
a: Option<Fp>,
|
||||
) -> Result<(), Error> {
|
||||
layouter.assign_region(
|
||||
|| "load private inputs",
|
||||
|mut region| {
|
||||
let row_offset = 0;
|
||||
self.config.s_range.enable(&mut region, row_offset)?;
|
||||
region.assign_advice(
|
||||
|| "private input 'a'",
|
||||
self.config.a_col,
|
||||
row_offset,
|
||||
|| a.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CoolCircuit {
|
||||
// Private input.
|
||||
a: Option<Fp>,
|
||||
}
|
||||
|
||||
impl Circuit<Fp> for CoolCircuit {
|
||||
type Config = CoolConfig;
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self { a: None }
|
||||
}
|
||||
|
||||
fn configure(cs: &mut ConstraintSystem<Fp>) -> Self::Config {
|
||||
CoolChip::configure(cs)
|
||||
}
|
||||
|
||||
fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<Fp>) -> Result<(), Error> {
|
||||
let chip = CoolChip::construct(config);
|
||||
chip.alloc_and_check(&mut layouter, self.a)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let params: Params<EqAffine> = Params::new(4);
|
||||
|
||||
let empty_circuit = CoolCircuit { a: None };
|
||||
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||
println!("Setup: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let circuit = CoolCircuit {
|
||||
a: Some(Fp::from(2)),
|
||||
};
|
||||
|
||||
// Create a proof
|
||||
let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
|
||||
create_proof(¶ms, &pk, &[circuit], &[&[]], &mut transcript)
|
||||
.expect("proof generation should not fail");
|
||||
let proof = transcript.finalize();
|
||||
println!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let msm = params.empty_msm();
|
||||
let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
|
||||
let verification = verify_proof(¶ms, pk.get_vk(), msm, &[&[]], &mut transcript);
|
||||
if let Err(err) = verification {
|
||||
panic!("error {:?}", err);
|
||||
}
|
||||
let guard = verification.unwrap();
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
println!("Verify: [{:?}]", start.elapsed());
|
||||
}
|
||||
|
||||
@@ -1,267 +0,0 @@
|
||||
use halo2::{
|
||||
circuit::{SimpleFloorPlanner, Cell, Chip, Layouter},
|
||||
pasta::{EqAffine, Fp},
|
||||
plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Expression, Selector, create_proof, verify_proof, keygen_vk, keygen_pk, Permutation},
|
||||
poly::{commitment::{Blind, Params}, Rotation},
|
||||
transcript::{Blake2bRead, Blake2bWrite, Challenge255},
|
||||
};
|
||||
use group::Curve;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct CoolConfig {
|
||||
a_col: Column<Advice>,
|
||||
b_col: Column<Advice>,
|
||||
permute: Permutation,
|
||||
s_range: Selector,
|
||||
s_mul: Selector,
|
||||
s_pub: Selector,
|
||||
}
|
||||
|
||||
struct CoolChip {
|
||||
config: CoolConfig
|
||||
}
|
||||
|
||||
impl Chip<Fp> for CoolChip {
|
||||
type Config = CoolConfig;
|
||||
type Loaded = ();
|
||||
|
||||
fn config(&self) -> &Self::Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
fn loaded(&self) -> &Self::Loaded {
|
||||
&()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Number {
|
||||
cell: Cell,
|
||||
value: Option<Fp>,
|
||||
}
|
||||
|
||||
impl CoolChip {
|
||||
fn construct(config: CoolConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
fn configure(cs: &mut ConstraintSystem<Fp>) -> CoolConfig {
|
||||
let a_col = cs.advice_column();
|
||||
let b_col = cs.advice_column();
|
||||
|
||||
let instance = cs.instance_column();
|
||||
|
||||
let permute = {
|
||||
// Convert advice columns into an "any" columns.
|
||||
let cols: [Column<Any>; 2] = [a_col.into(), b_col.into()];
|
||||
Permutation::new(cs, &cols)
|
||||
};
|
||||
|
||||
let s_range = cs.selector();
|
||||
let s_mul = cs.selector();
|
||||
let s_pub = cs.selector();
|
||||
|
||||
cs.create_gate("check", |cs| {
|
||||
let a = cs.query_advice(a_col, Rotation::cur());
|
||||
let s_range = cs.query_selector(s_range);
|
||||
vec![s_range * (a - Expression::Constant(Fp::from(2)))]
|
||||
});
|
||||
|
||||
cs.create_gate("mul", |cs| {
|
||||
let lhs = cs.query_advice(a_col, Rotation::cur());
|
||||
let rhs = cs.query_advice(b_col, Rotation::cur());
|
||||
let out = cs.query_advice(a_col, Rotation::next());
|
||||
let s_mul = cs.query_selector(s_mul);
|
||||
|
||||
vec![s_mul * (lhs * rhs + out * -Fp::one())]
|
||||
});
|
||||
|
||||
cs.create_gate("public input", |cs| {
|
||||
let a = cs.query_advice(b_col, Rotation::cur());
|
||||
let p = cs.query_instance(instance, Rotation::cur());
|
||||
let s = cs.query_selector(s_pub);
|
||||
|
||||
vec![s * (p + a * -Fp::one())]
|
||||
});
|
||||
|
||||
CoolConfig { a_col, b_col, permute, s_range, s_mul, s_pub }
|
||||
}
|
||||
|
||||
fn alloc_left(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<Fp>,
|
||||
value: Option<Fp>
|
||||
) -> Result<Number, Error> {
|
||||
layouter.assign_region(
|
||||
|| "load left private input",
|
||||
|mut region| {
|
||||
let cell = region.assign_advice(
|
||||
|| "private input 'a'",
|
||||
self.config.a_col,
|
||||
0,
|
||||
|| value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
Ok(Number { cell, value })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn check(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<Fp>,
|
||||
number: Number
|
||||
) -> Result<(), Error> {
|
||||
layouter.assign_region(
|
||||
|| "load private inputs",
|
||||
|mut region| {
|
||||
self.config.s_range.enable(&mut region, 0)?;
|
||||
|
||||
let a = region.assign_advice(
|
||||
|| "lhs",
|
||||
self.config.a_col,
|
||||
0,
|
||||
|| number.value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(&self.config.permute, number.cell, a)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn mul(
|
||||
&self,
|
||||
layouter: &mut impl Layouter<Fp>,
|
||||
a: Number,
|
||||
b: Number
|
||||
) -> Result<Number, Error> {
|
||||
let mut out = None;
|
||||
layouter.assign_region(
|
||||
|| "mul",
|
||||
|mut region| {
|
||||
self.config.s_mul.enable(&mut region, 0)?;
|
||||
|
||||
let lhs = region.assign_advice(
|
||||
|| "lhs",
|
||||
self.config.a_col,
|
||||
0,
|
||||
|| a.value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
let rhs = region.assign_advice(
|
||||
|| "rhs",
|
||||
self.config.b_col,
|
||||
0,
|
||||
|| b.value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(&self.config.permute, a.cell, lhs)?;
|
||||
region.constrain_equal(&self.config.permute, b.cell, rhs)?;
|
||||
|
||||
let value = a.value.and_then(|a| b.value.map(|b| a * b));
|
||||
let cell = region.assign_advice(
|
||||
|| "lhs * rhs",
|
||||
self.config.a_col,
|
||||
1,
|
||||
|| value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
out = Some(Number { cell, value });
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(out.unwrap())
|
||||
}
|
||||
|
||||
fn expose_public(&self, layouter: &mut impl Layouter<Fp>, num: Number) -> Result<(), Error> {
|
||||
layouter.assign_region(
|
||||
|| "expose public",
|
||||
|mut region| {
|
||||
self.config.s_pub.enable(&mut region, 0)?;
|
||||
|
||||
let out = region.assign_advice(
|
||||
|| "public advice",
|
||||
self.config.b_col,
|
||||
0,
|
||||
|| num.value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
region.constrain_equal(&self.config.permute, num.cell, out)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CoolCircuit {
|
||||
// Private input.
|
||||
a: Option<Fp>,
|
||||
}
|
||||
|
||||
impl Circuit<Fp> for CoolCircuit {
|
||||
type Config = CoolConfig;
|
||||
type FloorPlanner = SimpleFloorPlanner;
|
||||
|
||||
fn without_witnesses(&self) -> Self {
|
||||
Self { a: None }
|
||||
}
|
||||
|
||||
fn configure(cs: &mut ConstraintSystem<Fp>) -> Self::Config {
|
||||
CoolChip::configure(cs)
|
||||
}
|
||||
|
||||
fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<Fp>) -> Result<(), Error> {
|
||||
let chip = CoolChip::construct(config);
|
||||
let a = chip.alloc_left(&mut layouter, self.a)?;
|
||||
chip.check(&mut layouter, a.clone())?;
|
||||
let a2 = chip.mul(&mut layouter, a.clone(), a)?;
|
||||
chip.expose_public(&mut layouter, a2)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let k = 6;
|
||||
|
||||
let start = Instant::now();
|
||||
let params: Params<EqAffine> = Params::new(k);
|
||||
|
||||
let empty_circuit = CoolCircuit { a: None };
|
||||
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||
println!("Setup: [{:?}]", start.elapsed());
|
||||
|
||||
let start = Instant::now();
|
||||
let circuit = CoolCircuit {
|
||||
a: Some(Fp::from(2)),
|
||||
};
|
||||
|
||||
let mut public_inputs = pk.get_vk().get_domain().empty_lagrange();
|
||||
public_inputs[4] = Fp::from(4);
|
||||
|
||||
// Create a proof
|
||||
let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
|
||||
create_proof(¶ms, &pk, &[circuit], &[&[public_inputs.clone()]], &mut transcript)
|
||||
.expect("proof generation should not fail");
|
||||
let proof = transcript.finalize();
|
||||
println!("Prove: [{:?}]", start.elapsed());
|
||||
|
||||
let pubinput = params
|
||||
.commit_lagrange(&public_inputs, Blind::default())
|
||||
.to_affine();
|
||||
let pubinput_slice = &[pubinput];
|
||||
|
||||
let start = Instant::now();
|
||||
let msm = params.empty_msm();
|
||||
let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
|
||||
let verification = verify_proof(¶ms, pk.get_vk(), msm, &[pubinput_slice], &mut transcript);
|
||||
if let Err(err) = verification {
|
||||
panic!("error {:?}", err);
|
||||
}
|
||||
let guard = verification.unwrap();
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.eval());
|
||||
println!("Verify: [{:?}]", start.elapsed());
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
use halo2::{
|
||||
pasta::pallas,
|
||||
plonk::{Advice, Column, Instance as InstanceColumn, Selector},
|
||||
};
|
||||
|
||||
use halo2_ecc::chip::EccConfig;
|
||||
use halo2_poseidon::pow5t3::Pow5T3Config as PoseidonConfig;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config {
|
||||
pub primary: Column<InstanceColumn>,
|
||||
pub q_add: Selector,
|
||||
pub advices: [Column<Advice>; 10],
|
||||
pub ecc_config: EccConfig,
|
||||
pub poseidon_config: PoseidonConfig<pallas::Base>,
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
pub mod circuit;
|
||||
|
||||
use halo2::{
|
||||
arithmetic::{CurveExt, FieldExt},
|
||||
pasta::{Ep, Fq},
|
||||
};
|
||||
use orchard::constants::fixed_bases::{
|
||||
VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn pedersen_commitment(value: u64, blind: Fq) -> Ep {
|
||||
let hasher = Ep::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
|
||||
let V = hasher(&VALUE_COMMITMENT_V_BYTES);
|
||||
let R = hasher(&VALUE_COMMITMENT_R_BYTES);
|
||||
let value = Fq::from_u64(value);
|
||||
|
||||
V * value + R * blind
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
racket lisp/jj.rkt || exit $?
|
||||
python scripts/compile.py --supervisor jj.psm --output jubjub.zcd || exit $?
|
||||
cargo run --release --bin zkvm -- init jubjub.zcd jubjub.zts
|
||||
cargo run --release --bin zkvm -- prove jubjub.zcd jubjub.zts proofs/jubjub.params jubjub.prf
|
||||
cargo run --release --bin zkvm -- verify jubjub.zcd jubjub.zts jubjub.prf
|
||||
cargo run --release --bin zkvm -- show jubjub.prf
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python3 scripts/preprocess.py proofs/mimc.psm > /tmp/mimc.psm || exit $?
|
||||
python3 scripts/compile.py --supervisor /tmp/mimc.psm --output mimc.zcd || exit $?
|
||||
cargo run --release --bin zkvm -- init mimc.zcd mimc.zts
|
||||
cargo run --release --bin zkvm -- prove mimc.zcd mimc.zts proofs/mimc.params mimc.prf
|
||||
cargo run --release --bin zkvm -- verify mimc.zcd mimc.zts mimc.prf
|
||||
cargo run --release --bin zkvm -- show mimc.prf
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python3 scripts/preprocess.py proofs/mint2.psm > /tmp/mint2.psm || exit $?
|
||||
python3 scripts/compile.py --supervisor /tmp/mint2.psm --output mint.zcd || exit $?
|
||||
cargo run --release --bin mint
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
arg=$1
|
||||
gatewayd_path="./target/release/gatewayd"
|
||||
cashierd_path="./target/release/cashierd"
|
||||
darkfid_path="./target/release/darkfid"
|
||||
drk_path="./target/release/drk"
|
||||
|
||||
echo Running demo...
|
||||
|
||||
if [ "$arg" = "-d" ]; then
|
||||
echo DEBUG MODE
|
||||
gatewayd_path="./target/debug/gatewayd"
|
||||
cashierd_path="./target/debug/cashierd"
|
||||
darkfid_path="./target/debug/darkfid"
|
||||
drk_path="./target/debug/drk"
|
||||
fi
|
||||
|
||||
echo Open new tab and run:
|
||||
echo " $ " $drk_path --help
|
||||
|
||||
trap cleanup SIGINT
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
screen -X -S "gatewayd" quit
|
||||
screen -X -S "cashierd" quit
|
||||
screen -X -S "darkfid" quit
|
||||
echo Exit demo...
|
||||
}
|
||||
|
||||
# Start gateway daemon
|
||||
screen -S "gatewayd" -dm "$gatewayd_path" -v
|
||||
status=$?
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Failed to start gateway daemon: $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
# Start cashier daemon
|
||||
screen -S "cashierd" -dm "$cashierd_path" -v
|
||||
status=$?
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Failed to start cashier daemon: $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
# Start darkfi daemon
|
||||
screen -S "darkfid" -dm "$darkfid_path" -v
|
||||
status=$?
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Failed to start darkfi daemon: $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
# Exit with an error if it detects that either of the processes has exited.
|
||||
# Otherwise it loops forever, waking up every 60 seconds
|
||||
while sleep 60; do
|
||||
ps aux |grep "gatewayd" |grep -q -v grep
|
||||
PROCESS_1_STATUS=$?
|
||||
ps aux |grep "cashierd" |grep -q -v grep
|
||||
PROCESS_2_STATUS=$?
|
||||
ps aux |grep "darkfid" |grep -q -v grep
|
||||
PROCESS_3_STATUS=$?
|
||||
|
||||
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 -o $PROCESS_3_STATUS -ne 0 ]; then
|
||||
echo "One of the processes has already exited."
|
||||
cleanup
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
contract bits_decomposition
|
||||
param x
|
||||
{% for i in range(256) %}
|
||||
private b_{{i}}
|
||||
{% endfor %}
|
||||
|
||||
# x is unpacked into little endian order
|
||||
unpack_bits x b_0 b_255
|
||||
|
||||
{% for i in range(256) %}
|
||||
# (1 - b) * b == 0
|
||||
lc0_add_one
|
||||
lc0_sub b_{{i}}
|
||||
|
||||
lc1_add b_{{i}}
|
||||
|
||||
enforce
|
||||
{% endfor %}
|
||||
|
||||
{% for i in range(256) %}
|
||||
lc0_add b_{{i}}
|
||||
lc_coeff_double
|
||||
{% endfor %}
|
||||
lc_coeff_reset
|
||||
lc0_sub x
|
||||
lc1_add_one
|
||||
enforce
|
||||
end
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
a_u 15a36d1f0f390d8852a35a8c1908dd87a361ee3fd48fdf77b9819dc82d90607e
|
||||
a_v 015d8c7f5b43fe33f7891142c001d9251f3abeeb98fad3e87b0dc53c4ebf1891
|
||||
b_u 15a36d1f0f390d8852a35a8c1908dd87a361ee3fd48fdf77b9819dc82d90607e
|
||||
b_v 015d8c7f5b43fe33f7891142c001d9251f3abeeb98fad3e87b0dc53c4ebf1891
|
||||
@@ -1,103 +0,0 @@
|
||||
constant a 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000
|
||||
constant d 0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1
|
||||
constant one 0x0000000000000000000000000000000000000000000000000000000000000001
|
||||
|
||||
{% macro jubjub_add(P, x1, y1, x2, y2) -%}
|
||||
# Compute U = (x1 + y1) * (y2 - EDWARDS_A*x2)
|
||||
# = (x1 + y1) * (x2 + y2)
|
||||
private {{P}}_U
|
||||
set {{P}}_U {{ x1 }}
|
||||
add {{P}}_U {{ y1 }}
|
||||
local {{P}}_tmp
|
||||
set {{P}}_tmp {{ x2 }}
|
||||
add {{P}}_tmp {{ y2 }}
|
||||
mul {{P}}_U {{P}}_tmp
|
||||
|
||||
# assert (x1 + y1) * (x2 + y2) == U
|
||||
lc0_add {{ x1 }}
|
||||
lc0_add {{ y1 }}
|
||||
lc1_add {{ x2 }}
|
||||
lc1_add {{ y2 }}
|
||||
lc2_add {{P}}_U
|
||||
enforce
|
||||
|
||||
# Compute A = y2 * x1
|
||||
private {{P}}_A
|
||||
set {{P}}_A {{ y2 }}
|
||||
mul {{P}}_A {{ x1 }}
|
||||
# Compute B = x2 * y1
|
||||
private {{P}}_B
|
||||
set {{P}}_B {{ x2 }}
|
||||
mul {{P}}_B {{ y1 }}
|
||||
# Compute C = d*A*B
|
||||
private {{P}}_C
|
||||
load {{P}}_C d
|
||||
mul {{P}}_C {{P}}_A
|
||||
mul {{P}}_C {{P}}_B
|
||||
|
||||
# assert (d * A) * (B) == C
|
||||
lc0_add_coeff d {{P}}_A
|
||||
lc1_add {{P}}_B
|
||||
lc2_add {{P}}_C
|
||||
enforce
|
||||
|
||||
# Compute P.x = (A + B) / (1 + C)
|
||||
private {{P}}_x
|
||||
set {{P}}_x {{P}}_A
|
||||
add {{P}}_x {{P}}_B
|
||||
local {{P}}_x_denom
|
||||
load {{P}}_x_denom one
|
||||
add {{P}}_x_denom {{P}}_C
|
||||
divide {{P}}_x {{P}}_x_denom
|
||||
|
||||
lc0_add_one
|
||||
lc0_add {{P}}_C
|
||||
lc1_add {{P}}_x
|
||||
lc2_add {{P}}_A
|
||||
lc2_add {{P}}_B
|
||||
enforce
|
||||
|
||||
# Compute P.y = (U - A - B) / (1 - C)
|
||||
private {{P}}_y
|
||||
set {{P}}_y {{P}}_U
|
||||
sub {{P}}_y {{P}}_A
|
||||
sub {{P}}_y {{P}}_B
|
||||
local {{P}}_y_denom
|
||||
load {{P}}_y_denom one
|
||||
sub {{P}}_y_denom {{P}}_C
|
||||
divide {{P}}_y {{P}}_y_denom
|
||||
|
||||
lc0_add_one
|
||||
lc0_sub {{P}}_C
|
||||
lc1_add {{P}}_y
|
||||
lc2_add {{P}}_U
|
||||
lc2_sub {{P}}_A
|
||||
lc2_sub {{P}}_B
|
||||
enforce
|
||||
{%- endmacro %}
|
||||
|
||||
contract input_spend
|
||||
param x1
|
||||
param y1
|
||||
|
||||
param x2
|
||||
param y2
|
||||
|
||||
{{ jubjub_add("P", "x1", "y1", "x2", "y2") }}
|
||||
|
||||
public x3
|
||||
set x3 P_x
|
||||
public y3
|
||||
set y3 P_y
|
||||
|
||||
lc0_add x3
|
||||
lc1_add_one
|
||||
lc2_add P_x
|
||||
enforce
|
||||
|
||||
lc0_add y3
|
||||
lc1_add_one
|
||||
lc2_add P_y
|
||||
enforce
|
||||
end
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
{% include 'mimc_constants.psm' %}
|
||||
|
||||
contract mimc
|
||||
param left_0
|
||||
param right
|
||||
|
||||
{# Jinja cannot set variables inside loops so use this hack #}
|
||||
{% set ns = namespace(right="right") %}
|
||||
|
||||
{% for i in range(322) %}
|
||||
# Each round perform these steps:
|
||||
# xL, xR := xR + (xL + Ci)^3, xL
|
||||
|
||||
local mimc_const
|
||||
load mimc_const mimc_constant_{{i}}
|
||||
|
||||
private tmp_{{i}}
|
||||
set tmp_{{i}} left_{{i}}
|
||||
add tmp_{{i}} mimc_const
|
||||
square tmp_{{i}}
|
||||
|
||||
lc0_add left_{{i}}
|
||||
lc0_add_constant mimc_constant_{{i}}
|
||||
lc1_add left_{{i}}
|
||||
lc1_add_constant mimc_constant_{{i}}
|
||||
lc2_add tmp_{{i}}
|
||||
enforce
|
||||
|
||||
# new_xL = xR + (xL + Ci)^3
|
||||
# new_xL = xR + tmp * (xL + Ci)
|
||||
# new_xL - xR = tmp * (xL + Ci)
|
||||
private left_{{i+1}}
|
||||
set left_{{i+1}} left_{{i}}
|
||||
add left_{{i+1}} mimc_const
|
||||
mul left_{{i+1}} tmp_{{i}}
|
||||
add left_{{i+1}} {{ns.right}}
|
||||
|
||||
lc0_add tmp_{{i}}
|
||||
lc1_add left_{{i}}
|
||||
lc1_add_constant mimc_constant_{{i}}
|
||||
lc2_add left_{{i+1}}
|
||||
lc2_sub {{ns.right}}
|
||||
enforce
|
||||
|
||||
# xR = xL
|
||||
# right_{{i+1}} = left_{{i}}
|
||||
{% set ns.right = "left_" + i|string %}
|
||||
|
||||
# xL = new_xL
|
||||
{% endfor %}
|
||||
|
||||
public hash_result
|
||||
set hash_result left_322
|
||||
|
||||
lc0_add left_322
|
||||
lc1_add_one
|
||||
lc2_add hash_result
|
||||
enforce
|
||||
end
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
constant mimc_constant_0 0x4699afdd3f9ce9916eaffcfbef597c5009ae9d3209c3b15feb6928a4a8d4b59e
|
||||
constant mimc_constant_1 0x41e2431761fee4a40b468524d91b3d64590b3c242de10d18f55f0c5e3883ef02
|
||||
constant mimc_constant_2 0x5a04a1ea758bf1cc1140fcec1ce2c9d68da53d6cf7ee8dfeedfb2ee45db08c27
|
||||
constant mimc_constant_3 0x2e4b930078e93e73581d7b71120a8e8b9627955a0aabf139bbfa5feceaab2e3b
|
||||
constant mimc_constant_4 0x6a9db69e4fd0a3f94402cf22076bd18300c344c69bf665542129ad887f0030ab
|
||||
constant mimc_constant_5 0x4458f2de4e16ce2ead3fe9dd164cca36d2b70a25e71f55cf0c51ca553a4f83ad
|
||||
constant mimc_constant_6 0x04f539ab6ea2d344049219c720a16c4e6033f8360b124519fdbb6d441428143b
|
||||
constant mimc_constant_7 0x6b9c7b12a4b3cf92e2f2b386426058709573f9abdf1bcc5411dacd7ea0eaf8f3
|
||||
constant mimc_constant_8 0x4375e3120921697155b3ea15c32b9412adce3a8ff8e28e1b8c95935cc71ad853
|
||||
constant mimc_constant_9 0x041854bb643e9e5e5d8aa6e828dc4c732c8fa24192a160f40da85737372c5d0c
|
||||
constant mimc_constant_10 0x65d9cc7ab2a2060d198d66310a902bddeeb7f5150173190036d2fae68de1c2b9
|
||||
constant mimc_constant_11 0x1e7d2b472c6a40254a228b0543aff318084e7f6152617a6cf7fc405d917bfc37
|
||||
constant mimc_constant_12 0x35293381012ebaf649d8c6db4e4d5e594bd114c99c234ddff7b9b5f6f8a9ec36
|
||||
constant mimc_constant_13 0x3a50794418ac54a1467578ed61e34d8be5d52c5f188f42955fe8d5e257ad3e89
|
||||
constant mimc_constant_14 0x446d905f60110dbd51129896a63a0e34bb0502101ad6311998ad2dfd74818277
|
||||
constant mimc_constant_15 0x3eee70356bab144c54b5fc1095f9bce59c727a57a5582dcbbd5c3afc3c61ceca
|
||||
constant mimc_constant_16 0x40b08ae056833e12c82f7e15e2dc72febc15d3275b51ec70afaffa6ce8bbb3d0
|
||||
constant mimc_constant_17 0x205923e6eb137869a552b4857bb64f946c912f3335a94291ebb8b29ecd3e6034
|
||||
constant mimc_constant_18 0x2a6aebced756f7e33c466bca2169ba24c471a088c8363fe0a966a223fd3b59ea
|
||||
constant mimc_constant_19 0x566efaf4e022036a8e073fd9812376888ac9f37c794daebe3fa77b1a87bf109e
|
||||
constant mimc_constant_20 0x1ee814f2660e7272712d588477e458c06f8f06950402e97c542d3682ad5f9aed
|
||||
constant mimc_constant_21 0x257fe0ace4965622be247dba9185f108707f4ab16c910c03c565afab43b0fb4f
|
||||
constant mimc_constant_22 0x43e156f0cad02ff6b763645c97663ab72229bb0a34f975681359797ccd58093c
|
||||
constant mimc_constant_23 0x317f43b78cc26f0332a3ec3ec187332d4de0f2baf04f62fe76bee9b11256130b
|
||||
constant mimc_constant_24 0x076ca6cd23830e3b3ece767b774e1b2243408098a7c5b816e7c616cb88f6b916
|
||||
constant mimc_constant_25 0x14e30a644f034c72cf40b1bc790200c2e8ab3e750e38f3fb0160188e817e4560
|
||||
constant mimc_constant_26 0x02eb02bfbac795a497a0882d66b718bb23de64f9fe7644179ddd3241cc407942
|
||||
constant mimc_constant_27 0x644f175cf6f2268d451e5188e467c508bc91d870646de9297911be2aedf26daf
|
||||
constant mimc_constant_28 0x14aef8f4f5499a0387e521a1c6064094590f149c52fb99e37b583434ca6bd46c
|
||||
constant mimc_constant_29 0x2ddc7c6bba8895913f3deee128bc63b5e34797274de80da775c4a0c810ac60e6
|
||||
constant mimc_constant_30 0x46adc33428a63a20459699183272b14797a5a7d1d66079701d214bced9a4be71
|
||||
constant mimc_constant_31 0x552847d9a2a5b03f726b277ba01ad61c0e28114667e7a9e11229b83224f74349
|
||||
constant mimc_constant_32 0x624921e44f5811f76c06ab74a11ad56e5241e4c597e9d172ee3c862bf6d4b1fd
|
||||
constant mimc_constant_33 0x506af906fab5f9407ee71824d72dfcd99115c5a2eb53b55a1d5877910a645282
|
||||
constant mimc_constant_34 0x514ddde7e75b27ae6f31efb7375bc209dcdd0ab4c277ee0f8b362cb5211def31
|
||||
constant mimc_constant_35 0x2e3be2e2a10f8e24b411902d9578d44e2a4a5042036ecc397e1cc5ab88e76329
|
||||
constant mimc_constant_36 0x61755a2f6a9729a3bd8d21aea98f4cf885aa1751a714e251a517395711674bf5
|
||||
constant mimc_constant_37 0x68f8f91713d81c2a6d601411447e944c27f7a1862855b940ef3521cbf4074e96
|
||||
constant mimc_constant_38 0x32e6b3dfaa0162846620ace97838a93f48999b5bbc078964687c795a9e5b71a0
|
||||
constant mimc_constant_39 0x3c783bf0caa35bd381603b9e3aa5dbcc4ed4fc93b03d69a49fa15286a6374f8d
|
||||
constant mimc_constant_40 0x4a3f322f033de27244d79dd5c6c2f34d84c24c917ce95cfb6458d72124280e70
|
||||
constant mimc_constant_41 0x3ee0abb7af79168e05566994017fade2d69bdb55c4253f996362b73d49f3f70e
|
||||
constant mimc_constant_42 0x15498a06e80c6060320e9a01292ee1a805c2aafd7b92f76b5f5e8be515e0a3b3
|
||||
constant mimc_constant_43 0x02424410de65455350831f5b1c3554626f6bbf373ed0f627b42f0d3ec2fdd487
|
||||
constant mimc_constant_44 0x5886da407f6014665272b45d213cb388987503398d407732f278c9a35267622d
|
||||
constant mimc_constant_45 0x15f6180f287d2ef5d9d057dc18eb7df732d97632bfb31e93ac065dcf0c67fd40
|
||||
constant mimc_constant_46 0x65f5dc85c9660f184a09ee768ae9af0f62911af31920d3b5c49ac0360d261441
|
||||
constant mimc_constant_47 0x65751a6bbccb0ea7fd79fe7231d03d2f14ec6a24c5d9c4a77d1a86acf3d027a9
|
||||
constant mimc_constant_48 0x4c21c6990442cb96b2ca684c9d427dc41090447248378f50b4de15b616f1f133
|
||||
constant mimc_constant_49 0x34cde97ef5c2459e29dbad8324fbefa5097f744f737cc59ad2681e49dfa43f99
|
||||
constant mimc_constant_50 0x5df3e3787510f9e2b32beb2fdf76fc6d646b3fb94d4ede65309762fc515ffb55
|
||||
constant mimc_constant_51 0x30394778b396dd8191e78cb7627636eb82b15b0de788c1e2db2788b05caedd8b
|
||||
constant mimc_constant_52 0x695a64cc6953c658f40c1c2666715790410e302d3d902fcb809924896c2d1f4e
|
||||
constant mimc_constant_53 0x6a4fe5863990f4b4d588841b0e52c4dc7a8c4644edfec7c721ab66b162ec5de9
|
||||
constant mimc_constant_54 0x62e4428cb1856ae809589806e5e7869ab0fb818d6c0a696d94ee616fe549400e
|
||||
constant mimc_constant_55 0x0b1e8a6d6581c13b6888d0bd9816bda3695f917d03510d9b42452f3501e3d55a
|
||||
constant mimc_constant_56 0x5e5a2b767f853d0f0bf0e3cae872fb942065db112cb48a12dbce3ce4da28aa87
|
||||
constant mimc_constant_57 0x2c1c59e21a9741edbaf1e5a275c573bbeb395c6a79abdd0e532e000298dc8c00
|
||||
constant mimc_constant_58 0x25d648572388935cac47095b4f38b3ebe6519766a0d03bf7de9b4368b7bc1b58
|
||||
constant mimc_constant_59 0x475a00fdc58c8a7092cae8942af520dd5e0f476dc469f0c3e908da68be55e6ff
|
||||
constant mimc_constant_60 0x3fe62baf8e0a5286b0055e16e712ad06d233fa71fb374557d4c3d585e33dd37b
|
||||
constant mimc_constant_61 0x54d74923f593c55659f92b34bf5c05a400187e143850173786c8a1dd2f3a1283
|
||||
constant mimc_constant_62 0x6aa3afe84262b6c5bc8994a2c0e66a64a534904efcf47ead067fa09cd2d58a6a
|
||||
constant mimc_constant_63 0x2069d079cd963cec28ccac413172576ace57da0b4ab502c11289fff6ff2de6eb
|
||||
constant mimc_constant_64 0x364b3a05a8b1271aa61d5894b51a445c5896e86a535869b70e56e1e0f7f49f42
|
||||
constant mimc_constant_65 0x1c904753197233afda76661025e67f6a8e7a5c209292e151a7f34119397c281f
|
||||
constant mimc_constant_66 0x45f6d1ed8bc4395ccc6cfc90a1cf5f636248e966d82d040d795014f5d184b3ac
|
||||
constant mimc_constant_67 0x1bdbb396d84fe4c8b5b230e1c925e9f0f5f88faea9b713b319c7c11c307cbdbe
|
||||
constant mimc_constant_68 0x347c35497a65e93d8f4ec06c1546991841fd680868e145849195e38ef783d1a4
|
||||
constant mimc_constant_69 0x1d9c23cb0d4a20c384d629c6e706ebaf12fe0fc4eb0860c8175e687742e941cc
|
||||
constant mimc_constant_70 0x59378cc30bc5948d66a6f1671e84e2e9ef342e0e3dd682015d93f96a68159f3a
|
||||
constant mimc_constant_71 0x59992c34faff2238e03be3d6e87086a427e6eef2c5647a690363a9ddc0c82d67
|
||||
constant mimc_constant_72 0x60b13d9cae9b2504ca982c50b14ee5a628d40832bab95108e6640b9a8ef8a853
|
||||
constant mimc_constant_73 0x4cea35b5ebf7d7956c0c592d4238051c37bdb8bcb4c08fa29239ffaff00793bf
|
||||
constant mimc_constant_74 0x25344d0db88e9df26d216c287ddc36a958ba1e4d4c05a9cd59715de870d47e36
|
||||
constant mimc_constant_75 0x19a1c0a1f3aa80db57b014a2dad65eecf645fcd442a09b97e78d044a50ba58c3
|
||||
constant mimc_constant_76 0x32a6b9ba275d0204fd0e3de5fed3eac823aa8ce0ef5eca627fe92030e4506fe3
|
||||
constant mimc_constant_77 0x4e4f1056e9e3b8861117ba8bba1a1c37e784ef9e1358473aa55156e3b1523dff
|
||||
constant mimc_constant_78 0x710f51f9f3866ab261df0fad6ad3986f75d9990bf7776f4e4775f9c8f95045c2
|
||||
constant mimc_constant_79 0x48623d21c816d6a47a6339d9bda7ff31f2b32b8491c72967b93f2734ec37f64d
|
||||
constant mimc_constant_80 0x69aae3a126e0625c52d05e8c98ea912f56a582419cef7f13f31be66ec14bd43c
|
||||
constant mimc_constant_81 0x2f7264fc97a0ff9188c506d5df4bf3d4f28cb1d12fa2767e18d023f8a7e907b0
|
||||
constant mimc_constant_82 0x54bf8632b89211a06bbf9c0ee5ba2328b1f2cbc1892b76282599c0fb432d761d
|
||||
constant mimc_constant_83 0x0deb44dd3e20b34cfb473944f4f8f07b4d337da0fc18021777c983bf3e4e7f44
|
||||
constant mimc_constant_84 0x37a108a7b9e612231e21f0b4c7186163e3cc59325cbb17a39e1e25b4c4345dba
|
||||
constant mimc_constant_85 0x317515ddac6dcb33a4ac68d4c02c6d93d147b61cd892474292258ebceaf5ce83
|
||||
constant mimc_constant_86 0x38e225b4f524fa89f414976687473eb4c5f3edfe983dbdd07d3e8486f3b93c0a
|
||||
constant mimc_constant_87 0x636b27e505a14fb8362beb2e436582db991e3089e6edaeb9aaba3d67f58c8c60
|
||||
constant mimc_constant_88 0x28fd1afb8cf1e9c7594b5b8d6b50ff1f81aa19f211c5c271f2181836158bb625
|
||||
constant mimc_constant_89 0x1a8cf4f8569d80ca7d878d7a76d959956ac5e7edb37fbcfd2f5d130e3841dbc0
|
||||
constant mimc_constant_90 0x2cfbffcc25a0a01ab7cd1e700030d0e363ac170dd000397fa83d107a6d12bd54
|
||||
constant mimc_constant_91 0x325355d6824f71f550b102c6fa6c8c129de58d325174c5981c562e606a58c55f
|
||||
constant mimc_constant_92 0x1716f66b4ad2388a23ce111dd5ff7c04d4478dd81930050fdf0c4a90fcd6d381
|
||||
constant mimc_constant_93 0x02992cefec8ee9bef9602858d51c87a2c4180d9fe0c02e6c6003531010793572
|
||||
constant mimc_constant_94 0x2132b3fd309dd69a9f3c39b450534d857721dd5a2bcb23b479a29b08e8f8551e
|
||||
constant mimc_constant_95 0x369986658b8e7e4f990fd6fc09b99a056d81ee47c7a9e46b4109d8af0956678c
|
||||
constant mimc_constant_96 0x25e00309f0c3097a6500df9ed5587ec128b20a97379814b4a0522f7e775a4548
|
||||
constant mimc_constant_97 0x529a8ecdddfb500c68b664f7303dad768da802c29a933801b2199cf74a3470f5
|
||||
constant mimc_constant_98 0x3cf98a6dc8290785ede38da9455dbd28a64a1bda35a48d6c6b1b35ba6df3268b
|
||||
constant mimc_constant_99 0x127401f379aa992d492782910baee0fb331b3e9c1a66492c9b002a37999f356a
|
||||
constant mimc_constant_100 0x449dabe3e12e7b495e0421de157acbd4b3852cb824bba7171c8e3da565e3f95e
|
||||
constant mimc_constant_101 0x410d1d4fb041736101f5468ebdfd9380f2066593534339bc419f35d530c92cd7
|
||||
constant mimc_constant_102 0x09747f87db187d67e7881e1b64345754ec9bc9ec353e9b055bc377f1618ef17e
|
||||
constant mimc_constant_103 0x5fec471449175525c56b18200dd8ab96b2f9ee383849545628f0ceff76f631d8
|
||||
constant mimc_constant_104 0x0c7e402c723170d5dc5f15e229f4bacc5eb50b34dbfb6129215ee662288e159c
|
||||
constant mimc_constant_105 0x158896654586f5c3a34808ef7ab93def61fc9257d5b7631ed6869259a45d1d01
|
||||
constant mimc_constant_106 0x57ab3eab90ec38cfb23625e7110948e4b56e38a1ccc2cfffc344876d28aceddd
|
||||
constant mimc_constant_107 0x08d08f8650f5ca7bf03aad9a80ae09c697327a131827a9c2aec67d1d9f58064e
|
||||
constant mimc_constant_108 0x273607089f1e9c2b99812e032dfb62c359438c76556a15692a3de02b8c13df4d
|
||||
constant mimc_constant_109 0x55bf5cd5a1a89d7e3d1d274cc5b1b765e42a9eab5cfd32148c1633550ecfffce
|
||||
constant mimc_constant_110 0x5c4f6e0acb889fbb573583767535e95bc537641769c35063c0bd3a65812ade57
|
||||
constant mimc_constant_111 0x581faa1d0a57ef947001fd8e57eee26e645d15eebedb7ebb1d85581968544ca6
|
||||
constant mimc_constant_112 0x48b77ab45f5fb6d615bd759a6661097bb8a3b5c27ba35f1b127d2ee12f043bc4
|
||||
constant mimc_constant_113 0x590618389009da43c679b6254ae4cc86dbfa397981f4dff30e064e07bfdc9eab
|
||||
constant mimc_constant_114 0x3ef9bd95ccaa3c577ab98d3fad87fe69953bbbba6c8bbca0301a6c88e9bed8e6
|
||||
constant mimc_constant_115 0x2bc1dd87795feb2a5e8d98759371592ba7147ee4c2a3473d18c496ebe3721216
|
||||
constant mimc_constant_116 0x620ba5be31e353f1f3c72a4380f32c016f0746f5446f9e1743fb01fe6994051e
|
||||
constant mimc_constant_117 0x151d0bcf972db311553ef8da672b1c861d118e9b78da632d24c49d4a0fa177b7
|
||||
constant mimc_constant_118 0x01f1bda7ed65ad241d6fa13d8c5cb40cc335a0b2a31b433f2c65cb01e8dad5bc
|
||||
constant mimc_constant_119 0x4aec58578fdfd5e59d18063bdcc69086dae303518f5155facdc2824878862c53
|
||||
constant mimc_constant_120 0x1ca2d39cd13b6c690faf2be3da4d4517e28244fbf9ca0f8f4d80565205fb86f2
|
||||
constant mimc_constant_121 0x72432f39b454d6457ffae81f2e843df03c1526920384c50136beca0627f9054a
|
||||
constant mimc_constant_122 0x1910c2e6bb35a12e22ec46cd0db6185f352bf3581cf46d2f9c494daf8d94b993
|
||||
constant mimc_constant_123 0x4e47d6f9080e682d34ae07d5886c29869d16324c468782bea9c62334b583251f
|
||||
constant mimc_constant_124 0x3240024a0dd08da0c135caf8114ea8d333ab181e94a3a01edabb760a64adcee4
|
||||
constant mimc_constant_125 0x1669aabbd01c4541575f150981af0cf9a196e0b98908af53ea14b81734ecce5a
|
||||
constant mimc_constant_126 0x316aa08fd611919a73b60dc2b3175b3843f17035d71b9edf2f72c32850629574
|
||||
constant mimc_constant_127 0x4919d1e48c28eb1d36a689d8a5826c4ae4cd4e84a8347a9c9238b825a0b53a8e
|
||||
constant mimc_constant_128 0x4572211d4d1c8257d142ff2335eea65ccbf3177a982fed00931410f3bdf08c19
|
||||
constant mimc_constant_129 0x5d2d04f110bb9a50adf25427b232870f2be2307685f19df47f9b2f1bae984a04
|
||||
constant mimc_constant_130 0x472609c977c6854de75985c9154f70a7fda1843a38f10dd4985ab8dc353ad5a7
|
||||
constant mimc_constant_131 0x5c2ba4f8bec80b52e65afbe7b2ff41ad73542275e40acba8730403e9e33c7697
|
||||
constant mimc_constant_132 0x267614d22d526f429346fb2e9dcc4930880971780e85ef44a199feabe2b48227
|
||||
constant mimc_constant_133 0x1110d3da8ece3e4eda99c2d63f6724779af505b9527f0b191b34b5bfabbf5584
|
||||
constant mimc_constant_134 0x68fc77023c046909572d302630c6508922cbc03e6c6d9a05108bc8db71e045ff
|
||||
constant mimc_constant_135 0x1b6630a5ab959106f3951689fcbc6a757c97511d08a3d4652b8ee7eab820d575
|
||||
constant mimc_constant_136 0x2e34a9c19201971c6cffc366e7955b33d0b7dc59fbaf87cadeb8d0c099cfb541
|
||||
constant mimc_constant_137 0x060bd11957a053af7aec4b2c2caf7e227512d9e856552e5cf6f4ed4b04753bec
|
||||
constant mimc_constant_138 0x0d8a6987303d76b12f97eaeacfd783401ffef6ac2e994182eaa93843300385ae
|
||||
constant mimc_constant_139 0x0e9b15bfa73141c59edc9d11ec4ee316525ba53c4b91e4f1a8adb8d372e91dff
|
||||
constant mimc_constant_140 0x55215d958a6afccf90247026efb61dd9bae318cd31ad27746b227de8873add8c
|
||||
constant mimc_constant_141 0x4ccb674b94da03efd3404a424a422d42fd4f3a8b9f73de3aa7377e728400e797
|
||||
constant mimc_constant_142 0x256f31bdb0e0cad47ec44da9bdd1fc146d0284f1d71c596e12b0c690e202d1c4
|
||||
constant mimc_constant_143 0x60797d9977e8cf8484240c0ac4d3703818c096db8d61ca640bab83ea4e675919
|
||||
constant mimc_constant_144 0x57fd867a56f6fba130d5cd80d1aa2562ca3bdb6956892c0f66e8d9bbe1fe49e7
|
||||
constant mimc_constant_145 0x09115f248d518063beb8d89c11115a6b53ac2927b2eeb0c50b50b3e82c314e5e
|
||||
constant mimc_constant_146 0x6a10f8ecb4e14465b19148ae366be2452b809596eec80f4913a2240e5e89c98d
|
||||
constant mimc_constant_147 0x0399008978536884058e8b36c86b622d5da6cde04ceabb591fe8057153f6c7b2
|
||||
constant mimc_constant_148 0x2c7ba50ad84ce603d8206950a09277dbf59da814c5b5119763a208953d946812
|
||||
constant mimc_constant_149 0x02a697c90f23766d5fde4b61101665b865375243f1bde57522bcb4bcda33804d
|
||||
constant mimc_constant_150 0x3bba46c732127685e3a7c6963ec063f961bfa23dce70af06fbbdba02d295aa8a
|
||||
constant mimc_constant_151 0x206c47de6dfd8600586a42f98aea1284742671c605e7a274a306e188015e031d
|
||||
constant mimc_constant_152 0x608a94a91f8e4e1b0adf94c1af4992b0176fc84d8d79b881ec02d2613f4d9083
|
||||
constant mimc_constant_153 0x28f906b6e3e6d01ac90251789b81001bb5d96ec2f55be04354b37bd7211c8731
|
||||
constant mimc_constant_154 0x25c66f7f7c9db885d9f7d7b64bd555f7e2e939878a6f1f1056c0c5af008949a7
|
||||
constant mimc_constant_155 0x4992f08ef5816859cd16e02a367e55fb073cc08ba19fce061e83288caba6e308
|
||||
constant mimc_constant_156 0x432fd05cdbd6ce762396cc6b88f6db33f0e6daa1e4faf602a599575fe797979d
|
||||
constant mimc_constant_157 0x4961bcdf4ad6da150ed71fe78f84c9faaa28e63e378af83aedd33870e337c362
|
||||
constant mimc_constant_158 0x4d1025421a43054ecb8eab1d4ed666a8cfc7b3e1d3f5243bd945032b7ae19a1b
|
||||
constant mimc_constant_159 0x0eb68c99851461def5baf569dff154f8ac4591e8ad194f641dc5fcfbc157c07d
|
||||
constant mimc_constant_160 0x256cd6ef41e108838bc52d51af281be02ad6c5d2a3e6f49f2cb864bcf2397447
|
||||
constant mimc_constant_161 0x0df82b76b04d8813711f92ed2bc6dda5f32e4778b5f1b328bd3b2a3b82928645
|
||||
constant mimc_constant_162 0x73397a58cf55ae9d2b14647125725f053dc0a9d5d5599f67955b8b8ceb8c43d8
|
||||
constant mimc_constant_163 0x352a6762b6764cd234a5e7e24e1beaed50618b691be9e40d4b15813d6023439a
|
||||
constant mimc_constant_164 0x4ebe36c93f3561edd31170f6775e38889598f0b40a3a2967882b60c6bcf8d6f6
|
||||
constant mimc_constant_165 0x4af798462ebca10935795dcb09770d98e2a93bc25a99af876c1f080fdf04047e
|
||||
constant mimc_constant_166 0x6f9acbad33e5d972376f1f67457fb5565582c0cc233006fe51942c48479a3c9f
|
||||
constant mimc_constant_167 0x395558ce9453ad4999a1d87585bc88b08731882ae0ffbbec886db1cc3fc7ee62
|
||||
constant mimc_constant_168 0x17b48a7db220b2b4e4a3e9139168f050056e71049e4080ded3949222d3915dd2
|
||||
constant mimc_constant_169 0x13266faaffcb6e011f73a4065bb1f7bdc373571d1b9c0210674f4f9d18cdbf3f
|
||||
constant mimc_constant_170 0x0edbbed85597c4beb59685811f7f3c0ce807083c032e6c71e5869004bb37c93d
|
||||
constant mimc_constant_171 0x64a7409e0e833df31fb574e1c12f764ecf0e3d335cc53afcdc22ac13d7a81da8
|
||||
constant mimc_constant_172 0x730fbba0d85d06eabf3f517d4826457bacb2fa8c2f24168c1b026ada9eca5bf5
|
||||
constant mimc_constant_173 0x1ffdde6d216f269f8d25efca3b28590416ea7340d92df2c02d111e30302ba020
|
||||
constant mimc_constant_174 0x6551f0ba88e2b256f61e052c2ed98e5253fb7791614da7f7f10f9db1dbace96f
|
||||
constant mimc_constant_175 0x5a40abaaa2542543cd1710bab187798b01f6c7d93395e3a1cdaed5b8866018e9
|
||||
constant mimc_constant_176 0x7021fa2631484663ef5e14124c49b3078b460d77c9972b9f3aa8fe7bed79bed6
|
||||
constant mimc_constant_177 0x28e1b47a74ed1328c9cf0188bcce0e6bc8e32d808ad91d62d747382141e7c439
|
||||
constant mimc_constant_178 0x267bb1817a59e83c9cb67f740cb31fccde2ae0f6dc49745f826267f78136bc5a
|
||||
constant mimc_constant_179 0x6f2a6bdaf2152c1368e51b4d1ae3ce48bb8a62e00d92f2f9f21393c691243aee
|
||||
constant mimc_constant_180 0x00cd4b3d36b639b44a828c3dfe8e8da68a7cccaf7063fa92877683c0e5080869
|
||||
constant mimc_constant_181 0x3e8e056dee60929e925fdcd2395a9959202ef71b82a638fd1e3decba9051d016
|
||||
constant mimc_constant_182 0x651baeb3fea106c59cefec6a9c8973347a481a75b04f547d8d2f63a1ced57161
|
||||
constant mimc_constant_183 0x1e6ea48da02249378957d446d9603e4a1e0efd343426933d0cf5a1400148f654
|
||||
constant mimc_constant_184 0x5eb2faa76b282614614ae97db1e0bb722146ac8230739cf9abb35058ae7f6363
|
||||
constant mimc_constant_185 0x6400a9ba34a8ce081b7755a5241338c78c10c07ff6cc97ac94f29b23775922f3
|
||||
constant mimc_constant_186 0x5c475b1284568d5c55fae4840fd5bf9b9f8041fb4c75f3fd902681d97d4b09d2
|
||||
constant mimc_constant_187 0x037e3fa79fcab75541fe4ceed6404d2a89228694646835e0422fb558477fb128
|
||||
constant mimc_constant_188 0x39186a11b8693a21684796f4dd227523ac2782d6d23330d8287d77e19f106923
|
||||
constant mimc_constant_189 0x44b4264d680b2bfa7081436798dce5bc3b20bedf250dfb2103abdde5b3f24eb2
|
||||
constant mimc_constant_190 0x01fd3211afd7ab17103dd5a181b91982d83e69f9df9568ed132db65c23bfba2d
|
||||
constant mimc_constant_191 0x66bd19f66bf63ef557cd87c638d6a97f2853a284307ff04392e61b7a68e56b12
|
||||
constant mimc_constant_192 0x09e3ea8c3c87110454cb0045179ac850f74285652c6854351682cd1706b54f88
|
||||
constant mimc_constant_193 0x22b7ffce8814457850e403085d0f725dc72396144565f4542d5bf826f4627106
|
||||
constant mimc_constant_194 0x255b1285cd235b83bbdc8032f637a74bc8b33a798e2751969ebe67c593b578bb
|
||||
constant mimc_constant_195 0x5b568413938daa1acec17d776af723451fc067e63ed8a24d58cefc27ef7feca9
|
||||
constant mimc_constant_196 0x4fc38e950b447f3040484e58a7d106386da69400c9292640014886e33eb7596f
|
||||
constant mimc_constant_197 0x044e95a76627fade400c813061a56bd38ae137734ac1b7b11fce4a12eed6bb68
|
||||
constant mimc_constant_198 0x129d3939b05352392ee46921665e027d3cb9c9857f0b2f161bb1f0fdd58a74bf
|
||||
constant mimc_constant_199 0x327b98a9fc847d6b6d54a175aaed3678172d615d37cf1c4448c9d4588a2eb7c7
|
||||
constant mimc_constant_200 0x63675e996ad78bc6725b923b4cbeacf40f7d4b85bf38fd8b5ed0f63424779ab5
|
||||
constant mimc_constant_201 0x7374af204d7432c7954dbbd12ed973b79fd0a6d7109061ffd10ecb2f6942d5fd
|
||||
constant mimc_constant_202 0x0fdf70b408b29ce4bb3ef9a02c333ba7789fffbf2b17dc2ef4dce8714ada06a8
|
||||
constant mimc_constant_203 0x4373b306976a59fbd07f82bb44c4ee4e4a11806801960c5c18f32f7679321d3c
|
||||
constant mimc_constant_204 0x1b218fbc57953d8d44ab45c19993b223939a121a1e6bf87b4ca549e06699880a
|
||||
constant mimc_constant_205 0x09b95f647fc4e11ed6a4757be6287d3f4d6bbdc6da8173da072d7a5d046862b1
|
||||
constant mimc_constant_206 0x1def7155ba82eebd07611e2dd694a49dac9085004c1b4e9de2b4f0bf40c063fd
|
||||
constant mimc_constant_207 0x38921799f2fae22e5dc387e3b63a8d4d2210ad60690f61cce190bad2a304c035
|
||||
constant mimc_constant_208 0x2cfc11979ac028eea6636015cd2241a9ca2b9256bcdbae2f89df853751f63589
|
||||
constant mimc_constant_209 0x21e602b39eade2ce622e3da4c76124a5f9b2580296037a33f88044895aa8562c
|
||||
constant mimc_constant_210 0x25c9a818e3691a8d36cc881eed8513110fbcd2c855270ae265cc4a53283e2f4e
|
||||
constant mimc_constant_211 0x6d17e4bdef0620c74ce13ee9b219e49bf2c8ac57cb1882bca03c64ec7c7c69fc
|
||||
constant mimc_constant_212 0x2285fe01b02e1cb4331c2e86272f10d7e7daeac3d368b914e9115d832aab4e12
|
||||
constant mimc_constant_213 0x3fb801cc1a5264babd7f35a65091d15eb9b47a6f06ab9422defafaee4cd35a84
|
||||
constant mimc_constant_214 0x5b2ae60ec46971d3b3535743c3ab4d99f07ee2f551bfb2212ecfc7120169c8eb
|
||||
constant mimc_constant_215 0x5322e28426199923aab00dcb5aa2c0c92690628e69ddbeaa8a9e0b92e4d84aa4
|
||||
constant mimc_constant_216 0x1db225ddf28a651a6f809533078dfc8a006d4b76b59afde3d3356c7f26bf1ac2
|
||||
constant mimc_constant_217 0x600fcc0f370b76ed88186364efc8d0435ba4efe84abd6b2573e87e213cb405dc
|
||||
constant mimc_constant_218 0x007c21ae6a4471fb33141d353cb73f3769ee63d78cbc5d7e6a8c1bdb7cf3eb4f
|
||||
constant mimc_constant_219 0x17520db9848586770ced86adfca305209a0884592720f70eb91f9e3a22c23a94
|
||||
constant mimc_constant_220 0x3db8aeed94f87b37fc9cfee7a7c027605bec03af4965b840a8942b89fef39ecf
|
||||
constant mimc_constant_221 0x10b3102359b66388bf079dd2f30d8131ec4da41bf159fae392838a9708e1cfc9
|
||||
constant mimc_constant_222 0x0c9f537a5a0efc930019893a3fbd46c5e2a85b78b22b4bb60c0c1ec2da334a07
|
||||
constant mimc_constant_223 0x165f9cb0313efaf5a0636141f39c3ff22089c0f9c494ebc40e9e8060b84f149f
|
||||
constant mimc_constant_224 0x001879a49e2e539bf9e9c713416f517ee14f6e510a9cafb9a321fef9ca23ed49
|
||||
constant mimc_constant_225 0x32e53a1e65305675144ebd5bb49bdcf81879daab30fff361eba5cfef952184a3
|
||||
constant mimc_constant_226 0x51b4edb20a2bbb2daf144d4ab3b72a5a4cc956d9bd9e2ba5017c2163928118c3
|
||||
constant mimc_constant_227 0x140c9db4c384a0e3757a41ae5005b2557148cb3c190ab7101059053039d655ed
|
||||
constant mimc_constant_228 0x1737e47c806e74be09d8f7daf7c9d12ede33929f5152eda6c8c008064cfc1be3
|
||||
constant mimc_constant_229 0x23f3501123499df44f5cd31b08fa1338be61194a023c9101a41ce7518acddcdd
|
||||
constant mimc_constant_230 0x68dcbacbeb6727e3b47ef3a6291421496a78d81a645f2451c2cd89818715329b
|
||||
constant mimc_constant_231 0x2f1dd4d3ce3e7b49d67a4bca9ba8b5b64ee37a20496ddbc302aa8c1bed9b2fbf
|
||||
constant mimc_constant_232 0x2b5427a54294793e926c0ed030eff8b5020801ae8a46b1d7cecc49d01d2cd4a1
|
||||
constant mimc_constant_233 0x1bcdebbdce2545485d5db25d9776f7bdc31dc799c61cb726e20e0071e939e4c4
|
||||
constant mimc_constant_234 0x6021616995863e2b6fb9015892f2f361b60656bf1998239aa471d4c698564e9f
|
||||
constant mimc_constant_235 0x4816704f77b55fba8188d9424143ffd7b015587467072992b2482e9bacd4f072
|
||||
constant mimc_constant_236 0x60aad5cbecde71eae3fb3e8355137d5890f2947227093bacd23291a731720e79
|
||||
constant mimc_constant_237 0x5bff651adb907adde66b4a4810173bb8cc0cc618e6698e236979750865b68466
|
||||
constant mimc_constant_238 0x4dc639d5986ad912fc2632704ad03b039c6982fccad820b16ce2e519de54dcb0
|
||||
constant mimc_constant_239 0x1780c0f66f7afefb6b32a019956b2a209224b9eeba8a643a222f7355214be300
|
||||
constant mimc_constant_240 0x6d23740f70b21671e66d9bb35d7387b017dd56c78b65973db44e5479567c27a0
|
||||
constant mimc_constant_241 0x1784ada0fe2211721dff5b63c46ddbd0cc2a7161e42f24b26b10cf0a807398c9
|
||||
constant mimc_constant_242 0x3721b5cbdc714dc02db737a41bac0ad9dfd640229e4ef73c780f2abc7907a101
|
||||
constant mimc_constant_243 0x6777e0e8612172897bde7e5e4d7edafdfac32f855d07b645ef0a2c2b6815d7bd
|
||||
constant mimc_constant_244 0x5430480105f06250a915e429d5436268eeff94a54606848883d84eece231db3a
|
||||
constant mimc_constant_245 0x5b06f0578c8e419abaf9365b1e0e4605a270d831b886b1310c2b30830f70aa05
|
||||
constant mimc_constant_246 0x064faf1daa9415f3bf666dccf10e96a660e3c3e08945cecfad74bcf656a09b63
|
||||
constant mimc_constant_247 0x5a7cf453cdc309e004ac0d4b161686c9497ddd5333302ce1ac689d3cd3f15fe8
|
||||
constant mimc_constant_248 0x3d1cdaba6330736b0b9c17a27d3f31b58ea7b0aa1a46faa5cbc191faef9e41ef
|
||||
constant mimc_constant_249 0x59c894b434302a88c78f3438263ff4a3f82f27af2f086958497b75ba9ede3267
|
||||
constant mimc_constant_250 0x4f96eab2814accfe7cc529624df63fd4d9d3932ecace112a52d488ebd64f86a9
|
||||
constant mimc_constant_251 0x5c3395a99f651f587c1e9f88fb32ffde50f312874219daec0f67f604ba56f55a
|
||||
constant mimc_constant_252 0x10bc86369a85dae2cbcb60d1a110675555b1f29f01af909d0b0a452fd6f8aa0a
|
||||
constant mimc_constant_253 0x025c11c9d5846be858ed85b2706718d0859b14b5e6afafc50e5b7cab9390e88d
|
||||
constant mimc_constant_254 0x6a0df7099df32bbf845516682d8b2c40d5b238bab4493508146ec7da5280b31d
|
||||
constant mimc_constant_255 0x15dee1455b9289a97a4fb4561cd05cc4eaac7f45e2098e6db369c4e38780a898
|
||||
constant mimc_constant_256 0x6b00cd849365b050f85b3bcb73dc91ae063ed60360b053ccecd4ea226f5d3480
|
||||
constant mimc_constant_257 0x36ba01e51f6cce897b12718e2947d0ded1b43f1ad65045d9e80792cc0d2afbcf
|
||||
constant mimc_constant_258 0x705ec3f8f1bdd15381e69d0241b37349e11963b509f73dde27e4d00f7173e9d2
|
||||
constant mimc_constant_259 0x00259c2c2a277983602c80547343f0037a7a3c7edfdf98a1ffd16bea20204aa2
|
||||
constant mimc_constant_260 0x07ba65993dc66a3359f96e202f8408f9367d24e37a83164c622f682ef4d113d0
|
||||
constant mimc_constant_261 0x56324ef5c5a36793bc76d0c2a38e6ae35916ab04bc072325036d9e832981518d
|
||||
constant mimc_constant_262 0x3cdc6e8fc9101d4e6be6b5fb368a3911ac13c4090ea7da9f345cd5f7ae7b1e6c
|
||||
constant mimc_constant_263 0x3fe62a321b08da7f8f6cd2080867b98b6c9f54bf910bac77db5a71da68b18270
|
||||
constant mimc_constant_264 0x53915ca5503403181327eea9143a99782e31f1636a324a946882376fb9d07681
|
||||
constant mimc_constant_265 0x45ec1e9c297bdd973aec556197b1168f8a55b0d7bb0519b5db479f95d11cd045
|
||||
constant mimc_constant_266 0x7310ab366f789b5264f16fd563b6dd31462f3e352a92fbb5e2357a9fbb9a1f16
|
||||
constant mimc_constant_267 0x739ebe2484fabba7b18d7f3a213bb9d3bb2d78a8c05f41515aa20533b933cc2e
|
||||
constant mimc_constant_268 0x048f8d7f23612a95c09d90137f7a4d87e340a1e83ec3c94284d6784ea8006423
|
||||
constant mimc_constant_269 0x49a59faf4bbf57ee29b5e186bb0008a4ec74c8fdb7ea8fe7e1aa46bc40873b50
|
||||
constant mimc_constant_270 0x5cf260d13f5da4870855a40e71d4effda202f310a955db2d140e9317e4238998
|
||||
constant mimc_constant_271 0x38c2eba027b51ab146dc61e33b7403789b63641a5cba018829e3dfc9336cbcb8
|
||||
constant mimc_constant_272 0x1f90a83ada4e0d548c8beea8f902f4bdd8466948161fe2760a0127f44a0edea8
|
||||
constant mimc_constant_273 0x6b65cc39e2d766f83e8f6f59fd5e40290bf8b887c99da8c166417d5a9cae1444
|
||||
constant mimc_constant_274 0x1da9f1f317f97e9c6132dc6808def44d32daa0c2dbcffe580d8f35b85400ccc3
|
||||
constant mimc_constant_275 0x3df94f558d1e935080d48183a3e742f6be2992f5aea51387f01c90219e980fa2
|
||||
constant mimc_constant_276 0x59974c89246e978cbee6e84478252843235f550eb7ba45324d4a7ea572ca7e2b
|
||||
constant mimc_constant_277 0x094be891b94edbc55530775ac31dd8f5ac0d1e2462579c158ce2f28843a2e9b2
|
||||
constant mimc_constant_278 0x02c997879aff55f85e9e19e36a32758b868a0504ff0cb4a704fabdb897f308bd
|
||||
constant mimc_constant_279 0x090a6946efff80828d498845e43aebaf02f19cc8a5459db7b12952e4924e1fd1
|
||||
constant mimc_constant_280 0x3cf7d767a121eb81462c2731ee18da4f5579e007ed7e198ed9c74d0e4122d247
|
||||
constant mimc_constant_281 0x4dafcb7ed415b248c5f169092d29b0f5d213e599e2bf15ade507d9ae2c9d764d
|
||||
constant mimc_constant_282 0x5204fb985e7a86bb77fd705bf71787c4a09b97e7729318e6828a422f70aabcea
|
||||
constant mimc_constant_283 0x0e1b38375d5ded933a6c9d7512ade1e96679651be670f381f875dd62c7279827
|
||||
constant mimc_constant_284 0x6b612638db66a469241a60b7222956ca0364f2d77ea8849aeb99fad2a0b5637f
|
||||
constant mimc_constant_285 0x3626c1544bd18d8a9bde32d6210aa6179839b1ebefb87fdb914d3735db50f92e
|
||||
constant mimc_constant_286 0x222fd118f0cc69ef015f43fdd95a4db3fc08eec734f4cd3fce78e73348373e03
|
||||
constant mimc_constant_287 0x369885b7348e2be8c21dce937e248cc6c390c703a09dddbb88b39bbfb3fa2943
|
||||
constant mimc_constant_288 0x0794753806f2502ff43f7b8c4990e446c37677a49f78e0a8e38622a23c34eb60
|
||||
constant mimc_constant_289 0x4b9b69b8b54c2ba38a23c409263b2ea543ba2082b6fded12c3c9b9dc754c4202
|
||||
constant mimc_constant_290 0x06fae323404cc19a099fb298803a76737720c25913e21f38a75f1c8e63a96b9c
|
||||
constant mimc_constant_291 0x50461e3977f12ec2de486071fc3924cd1aef82a6bc9fbde215eaddee6780de1d
|
||||
constant mimc_constant_292 0x5ff12618767830d17a759dadc62c40221cc848ef84da8cd91b76e5ca59ccaa37
|
||||
constant mimc_constant_293 0x6b7bdeac8d4dc989219510a928aa2e2a8995f4aba16e9f59d85e88ae3f6f5f5f
|
||||
constant mimc_constant_294 0x5fbc48469f2e94eaee4ce3cc7af5c45f27a6532f0b7d8aaad76e61091a319ecd
|
||||
constant mimc_constant_295 0x024ec0f964b1ce01b08352c231662c238c623cd66a2da4ef330debc7323dba8e
|
||||
constant mimc_constant_296 0x0dfd978f5c1e804bd89e9d579edb44c49335296cd5948420d7650775cf88fc0c
|
||||
constant mimc_constant_297 0x57ecafcf80a257780a9bbac3793c3e772fde0c88d6ce8e39399c7eb0a7e76d6a
|
||||
constant mimc_constant_298 0x705b423e84afdccba45b0286397d1a29896cc1dc3fb41721e9e14942a2c13db6
|
||||
constant mimc_constant_299 0x61efd69d156931b397d7aebd87d6c7599f6a5e2925cb7d8891fd751b7757c486
|
||||
constant mimc_constant_300 0x5b0a8e0bc9d55850e65cb119b6b43abd5eda13de38ffd6e45130a6b2c7184251
|
||||
constant mimc_constant_301 0x2ee9eb134a2f83e93bb4b09c71da3e7810d9a2bd01acaacf70fc7b43ccc2fec6
|
||||
constant mimc_constant_302 0x136a3734420b9a29249f23e3292d871653540c3a86fdfbdbb655596aac99d0ce
|
||||
constant mimc_constant_303 0x11ea5a840d53c0f0eaa111e6f43d953cdadcddedd8b7658d82266fd0897cd71a
|
||||
constant mimc_constant_304 0x51a4d6a93c09813a72f272b043ef5cf88fe27eeadb2065cb75c95620874ea281
|
||||
constant mimc_constant_305 0x00b698d1b30b8486b7fb7cafdae54bb93ac182be3623f1feffa7edc12486d4e8
|
||||
constant mimc_constant_306 0x22386f894f2a9326c7ab4cfbceae435cb69f3e359ee49946dc566f242f4238de
|
||||
constant mimc_constant_307 0x636d98aea6cb6afe50fd1e96bb8bfdf18a9d54a87e66fd79e3dff80abda98c18
|
||||
constant mimc_constant_308 0x067a4de70930459165ff7d84a0dc375adb145ac07e67eb0e1fadebd4e2610eeb
|
||||
constant mimc_constant_309 0x64721850463f2d1dfe148e429e472914d67d9867409de6c39150225106d4d425
|
||||
constant mimc_constant_310 0x6c87827aa64247be6bb132c49e271a6e23c54c8334f2c3eca5551b4ae5260f05
|
||||
constant mimc_constant_311 0x65cbbc751ea4f5e7956628b8645708187b37f2d65c6c297a5854355256de476e
|
||||
constant mimc_constant_312 0x6bf24b343856b4066e2835b1fe3e5d16496a36f41386c2afd44d001ba886fdc7
|
||||
constant mimc_constant_313 0x41d82825d409ab7c996773b516f6720e34cbfdebdc9c069fa579dcea11ef44f6
|
||||
constant mimc_constant_314 0x45f741f2e9481a85b86467ab30d363fd0328e33d53fce6b39286c2494ee7bd28
|
||||
constant mimc_constant_315 0x6c06f72d4e071f9c1ddca4f9ea231853f6d8c5e9b7418e9c564c995912d19c18
|
||||
constant mimc_constant_316 0x154f9ecfb65370a8b59a12cd736348aead2e59a7e3701d20a669bec15363fe62
|
||||
constant mimc_constant_317 0x0c4d910fbd3b57be6d6680e8d2db47c1454712b240b78468cb764702be5c1aec
|
||||
constant mimc_constant_318 0x0e1ac575e1125f5ee86da3342018bc4f3c1e2310148043d5074eb4ee22fc55b6
|
||||
constant mimc_constant_319 0x273531c7d0d03d8f97b722ef1f0c324dac39f804e0222202f7502946647ef332
|
||||
constant mimc_constant_320 0x101464d19cf380958e5aef1084736db89f4cb131033ae670f6de0a5cf9d92b73
|
||||
constant mimc_constant_321 0x597cdd384abdad1beccc73fb39f74a18eb44d056951d602c2ef6ef6448fc5626
|
||||
@@ -1,92 +0,0 @@
|
||||
# :set syntax=pism
|
||||
# :source ../scripts/pism.vim
|
||||
constant G_VCV FixedGenerator
|
||||
constant G_VCR FixedGenerator
|
||||
constant CRH_IVK BlakePersonalization
|
||||
#constant JUBJUB_FR_CAPACITY BinarySize
|
||||
#constant NOTE_COMMIT PedersenPersonalization
|
||||
|
||||
contract mint_contract
|
||||
# Value commitment
|
||||
param value U64
|
||||
param asset_id Fr
|
||||
param randomness_value Fr
|
||||
param randomness_asset Fr
|
||||
|
||||
param serial Fr
|
||||
param randomness_coin Fr
|
||||
param public Point
|
||||
start
|
||||
# Witness input values
|
||||
u64_as_binary_le value param:value
|
||||
fr_as_binary_le asset_id param:asset_id
|
||||
fr_as_binary_le randomness_value param:randomness_value
|
||||
fr_as_binary_le randomness_asset param:randomness_asset
|
||||
fr_as_binary_le serial param:serial
|
||||
fr_as_binary_le randomness_coin param:randomness_coin
|
||||
|
||||
witness public param:public
|
||||
assert_not_small_order public
|
||||
|
||||
# Make value commitment
|
||||
# V = v * G_VCV + r * G_VCR
|
||||
|
||||
ec_mul_const vcv value G_VCV
|
||||
ec_mul_const rcv randomness_value G_VCR
|
||||
ec_add cv vcv rcv
|
||||
# emit cv
|
||||
emit_ec cv
|
||||
|
||||
# Make asset_id commitment
|
||||
# A = a * G_VCV + r_a * G_VCR
|
||||
|
||||
ec_mul_const vca asset_id G_VCV
|
||||
ec_mul_const rca randomness_asset G_VCR
|
||||
ec_add ca vca rca
|
||||
# emit ca
|
||||
emit_ec ca
|
||||
|
||||
|
||||
# Make the coin
|
||||
# C = Hash(public_key, value, asset_id, serial, randomness_coin)
|
||||
|
||||
# Build the preimage to hash
|
||||
alloc_binary preimage
|
||||
|
||||
# public_key
|
||||
ec_repr repr_public public
|
||||
binary_extend preimage repr_public
|
||||
|
||||
# value
|
||||
binary_extend preimage value
|
||||
|
||||
# Fr values are 252 bits so we need to pad it with extra 0s
|
||||
# to match the Rust values which are 256 bits
|
||||
{% macro binary_put_fr(binary, var) -%}
|
||||
binary_extend {{ binary }} {{ var }}
|
||||
{% for n in range(4) %}
|
||||
alloc_const_bit zero_bit false
|
||||
binary_push {{ binary }} zero_bit
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
# serial
|
||||
{{ binary_put_fr("preimage", "serial") }}
|
||||
|
||||
# randomness_coin
|
||||
{{ binary_put_fr("preimage", "randomness_coin") }}
|
||||
|
||||
# asset_id
|
||||
{{ binary_put_fr("preimage", "asset_id") }}
|
||||
|
||||
# Public key: SubgroupPoint = 256 bits
|
||||
# Value: u64 = 64 bits
|
||||
# AssetID: Fr = 252 + 4 bits padding
|
||||
# Serial: Fr = 252 + 4 bits padding
|
||||
# Randomness coin Fr = 252 + 4 bits padding
|
||||
# TOTAL: 1088 bits for preimage
|
||||
static_assert_binary_size preimage 1088
|
||||
blake2s coin preimage CRH_IVK
|
||||
emit_binary coin
|
||||
end
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"constants": {
|
||||
"G_SPEND": {
|
||||
"maps_to": "zcash_proofs::constants::SPENDING_KEY_GENERATOR"
|
||||
},
|
||||
"G_PROOF": {
|
||||
"maps_to": "zcash_proofs::constants::PROOF_GENERATION_KEY_GENERATOR"
|
||||
},
|
||||
"CRH_IVK": {
|
||||
"maps_to": "zcash_primitives::constants::CRH_IVK_PERSONALIZATION"
|
||||
},
|
||||
"PRF_NF": {
|
||||
"maps_to": "zcash_primitives::constants::PRF_NF_PERSONALIZATION"
|
||||
},
|
||||
"G_VCV": {
|
||||
"maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR"
|
||||
},
|
||||
"G_VCR": {
|
||||
"maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR"
|
||||
},
|
||||
"JUBJUB_FR_CAPACITY": {
|
||||
"maps_to": "jubjub::Fr::CAPACITY as usize"
|
||||
},
|
||||
"NOTE_COMMIT": {
|
||||
"maps_to": "pedersen_hash::Personalization::NoteCommitment"
|
||||
},
|
||||
"MERKLE_0": {
|
||||
"maps_to": "pedersen_hash::Personalization::MerkleTree(0)"
|
||||
},
|
||||
"MERKLE_1": {
|
||||
"maps_to": "pedersen_hash::Personalization::MerkleTree(1)"
|
||||
},
|
||||
"MERKLE_2": {
|
||||
"maps_to": "pedersen_hash::Personalization::MerkleTree(2)"
|
||||
},
|
||||
"MERKLE_3": {
|
||||
"maps_to": "pedersen_hash::Personalization::MerkleTree(3)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
# :set syntax=pism
|
||||
# :source ../scripts/pism.vim
|
||||
constant G_VCV FixedGenerator
|
||||
constant G_VCR FixedGenerator
|
||||
constant G_SPEND FixedGenerator
|
||||
constant G_PROOF FixedGenerator
|
||||
constant G_NOTE_COMMIT_R FixedGenerator
|
||||
constant G_NULL FixedGenerator
|
||||
constant CRH_IVK BlakePersonalization
|
||||
constant NOTE_COMMIT PedersenPersonalization
|
||||
constant MERKLE_0 PedersenPersonalization
|
||||
constant MERKLE_1 PedersenPersonalization
|
||||
constant MERKLE_2 PedersenPersonalization
|
||||
constant MERKLE_3 PedersenPersonalization
|
||||
# ...
|
||||
constant PRF_NF BlakePersonalization
|
||||
constant JUBJUB_FR_CAPACITY ByteSize
|
||||
|
||||
contract input_spend
|
||||
param value U64
|
||||
param randomness Fr
|
||||
param ak Point
|
||||
param ar Fr
|
||||
param nsk Fr
|
||||
param g_d Point
|
||||
param commitment_randomness Fr
|
||||
param auth_path_0_0 Scalar
|
||||
param auth_path_0_1 Bool
|
||||
param auth_path_1_0 Scalar
|
||||
param auth_path_1_1 Bool
|
||||
# ...
|
||||
param anchor Scalar
|
||||
start
|
||||
# let rk: Point = ak + ar * G_SPEND
|
||||
witness ak param:ak
|
||||
assert_not_small_order ak
|
||||
fr_as_binary_le ar param:ar
|
||||
ec_mul_const ar ar G_SPEND
|
||||
ec_add rk ak ar
|
||||
# emit rk
|
||||
emit_ec rk
|
||||
|
||||
# let nk: Point = nsk * G_PROOF
|
||||
fr_as_binary_le nsk param:nsk
|
||||
ec_mul_const nk nsk G_PROOF
|
||||
|
||||
# let mut ivk_preimage: BinaryNumber = []
|
||||
alloc_binary ivk_preimage
|
||||
# ivk_preimage.put(ak)
|
||||
ec_repr repr_ak ak
|
||||
binary_extend ivk_preimage repr_ak
|
||||
|
||||
# let mut nf_preimage: BinaryNumber = []
|
||||
alloc_binary nf_preimage
|
||||
ec_repr repr_nk nk
|
||||
binary_clone repr_nk repr_nk2
|
||||
# ivk_preimage.put(nk)
|
||||
binary_extend ivk_preimage repr_nk
|
||||
# nf_preimage.put(nk)
|
||||
binary_extend ivk_preimage repr_nk2
|
||||
|
||||
# assert ivk_preimage.len() == 512
|
||||
static_assert_binary_size ivk_preimage 512
|
||||
# assert nf_preimage.len() == 256
|
||||
static_assert_binary_size nf_preimage 256
|
||||
|
||||
# let mut ivk = blake2s(ivk_preimage, CRH_IVK)
|
||||
blake2s ivk ivk_preimage CRH_IVK
|
||||
# ivk.truncate(JUBJUB_FR_CAPACITY)
|
||||
binary_truncate ivk JUBJUB_FR_CAPACITY
|
||||
|
||||
# let pk_d: Point = ivk * g_d
|
||||
witness g_d param:g_d
|
||||
assert_not_small_order g_d
|
||||
ec_mul pk_d ivk g_d
|
||||
|
||||
# let cv: Point = value * G_VCV + rcv * G_VCR
|
||||
u64_as_binary_le value_bits param:value
|
||||
ec_mul_const value value_bits G_VCV
|
||||
fr_as_binary_le rcv param:randomness
|
||||
ec_mul_const rcv rcv G_VCR
|
||||
ec_add cv value rcv
|
||||
# emit cv
|
||||
emit_ec cv
|
||||
|
||||
# let mut note_contents: BinaryNumber = []
|
||||
alloc_binary note_contents
|
||||
|
||||
# note_contents.put(value)
|
||||
binary_extend note_contents value
|
||||
# note_contents.put(g_d)
|
||||
ec_repr repr_g_d g_d
|
||||
binary_extend note_contents repr_g_d
|
||||
# note_contents.put(p_k)
|
||||
ec_repr repr_p_k p_k
|
||||
binary_extend note_contents repr_p_k
|
||||
# assert note_contents.len() == 64 + 256 + 256
|
||||
static_assert_binary_size ivk_preimage 576
|
||||
|
||||
# let mut cm = pedersen_hash(note_contents, NOTE_COMMIT)
|
||||
pedersen_hash cm note_contents NOTE_COMMIT
|
||||
# cm += commitment_randomness * G_NOTE_COMMIT_R
|
||||
fr_as_binary_le rcm param:commitment_randomness
|
||||
ec_mul_const cm1 rcm G_NOTE_COMMIT_R
|
||||
ec_add cm cm cm1
|
||||
|
||||
# let mut position = []
|
||||
alloc_binary position
|
||||
# let mut cur: Scalar = cm.u
|
||||
ec_get_u cur cm
|
||||
|
||||
# There are no loops in this language.
|
||||
# ZK proofs must have a fixed size.
|
||||
# So in this assembly we UNROLL all loops.
|
||||
# for i in range(auth_path.size()):
|
||||
#
|
||||
# Here we give the example of loop 0.
|
||||
# Replace the indexes with the value i
|
||||
# Below line is auth_path[0].1
|
||||
|
||||
# let (node: Scalar, is_right: Bool) = auth_path[i]
|
||||
# position.push(is_right)
|
||||
alloc_bit cur_is_right param:auth_path_0_1
|
||||
clone_bit cur_is_right2 cur_is_right
|
||||
binary_push position cur_is_right2
|
||||
alloc_num path_element param:auth_path_0_0
|
||||
# let (left: Scalar, right: Scalar) = swap_if(is_right, cur, node)
|
||||
conditionally_reverse ulur cur path_element is_right
|
||||
get_0 ul ulur
|
||||
get_1 ur ulur
|
||||
# let mut preimage: BinaryNumber = []
|
||||
alloc_binary preimage
|
||||
# preimage.put(left)
|
||||
num_to_binary ul_bits ul
|
||||
binary_extend preimage ul_bits
|
||||
# preimage.put(right)
|
||||
num_to_binary ur_bits ur
|
||||
binary_extend preimage ur_bits
|
||||
# cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
pedersen_hash curhash preimage MERKLE_0
|
||||
ec_get_u cur curhash
|
||||
# ... repeat the above N times
|
||||
|
||||
# enforce cur == rt
|
||||
alloc_num rt param:anchor
|
||||
num_enforce_equal cur rt
|
||||
# emit rt
|
||||
emit_num rt
|
||||
|
||||
# let rho: Point = rho + position * G_NULL
|
||||
ec_mul_const position position_bits G_NULL
|
||||
ec_add rho rho position
|
||||
# nf_preimage.put(rho)
|
||||
ec_repr repr_rho rho
|
||||
binary_extend nf_preimage repr_rho
|
||||
# assert nf_preimage.len() == 512
|
||||
static_assert_binary_size nf_preimage 512
|
||||
|
||||
# let nf: BinaryNumber = blake2s(nf_preimage, PRF_NF)
|
||||
blake2s nf nf_preimage PRF_NF
|
||||
emit_binary nf
|
||||
end
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
# You will need this repo:
|
||||
# https://github.com/zcash/librustzcash/
|
||||
# Then compare this code to the file:
|
||||
# librustzcash/zcash_proofs/src/circuit/sapling.rs
|
||||
|
||||
# What is the LC stuff?
|
||||
# Difference between AllocatedNum and Num
|
||||
# Why BlsScalar vs JJScalar?
|
||||
const:
|
||||
G_VCV: Point
|
||||
G_VCR: Point
|
||||
G_SPEND: Point
|
||||
G_PROOF: Point
|
||||
G_NOTE_COMMIT_R: Point
|
||||
G_NULL: Point
|
||||
|
||||
CRH_IVK: Blake2sPersonalization
|
||||
NOTE_COMMIT: PedersenPersonalization
|
||||
MERKLE: list<PedersenPersonalization>
|
||||
PRF_NF: Blake2sPersonalization
|
||||
|
||||
def value_commit(value: u64, randomness: Scalar) -> (Point, list<bool>):
|
||||
let value_bits: list<bool> = value as list<bool>
|
||||
let value: Point = value * G_VCV
|
||||
|
||||
let rcv: list<bool> = randomness as list<bool>
|
||||
let rcv: Point = rcv * G_VCR
|
||||
|
||||
let cv: Point = value + rcv
|
||||
return cv, value_bits
|
||||
|
||||
# The parameters to this function are the same as in:
|
||||
# struct Spend
|
||||
def input_burn(
|
||||
value: u64, # ValueCommitment.value
|
||||
randomness: Scalar, # ValueCommitment.randomness
|
||||
|
||||
ak: Point, # from ProofGenerationKey
|
||||
ar: Scalar,
|
||||
|
||||
nsk: Scalar, # from ProofGenerationKey
|
||||
|
||||
g_d: Point, # Computed from payment_address
|
||||
|
||||
commitment_randomness: Scalar,
|
||||
|
||||
auth_path: list<(Scalar, bool)>,
|
||||
|
||||
anchor: Scalar
|
||||
) -> (Point, Point, Point, list<bool>):
|
||||
let ak = witness(ak)
|
||||
ak.assert_not_small_order()
|
||||
|
||||
let ar: list<bool> = ar as list<bool>
|
||||
let ar: Point = ar * G_SPEND
|
||||
|
||||
let rk: Point = ak + ar
|
||||
|
||||
let nsk: list<bool> = nsk as list<bool>
|
||||
let nk: Point = nsk * G_PROOF
|
||||
|
||||
let mut ivk_preimage: list<bool> = []
|
||||
# Must be list<bool> as well
|
||||
ivk_preimage.extend(ak.repr())
|
||||
|
||||
let mut nf_preimage: list<bool> = []
|
||||
let nk_repr: list<bool> = nk.repr()
|
||||
ivk_preimage.extend(nk_repr)
|
||||
nf_preimage.extend(nk_repr)
|
||||
|
||||
assert len(ivk_preimage) == 512
|
||||
assert len(nf_preimage) == 256
|
||||
|
||||
let mut ivk: list<bool> = blake2s(ivk_preimage, CRH_IVK)
|
||||
ivk.truncate(Scalar::CAPACITY)
|
||||
|
||||
let g_d: Point = witness g_d
|
||||
g_d.assert_not_small_order()
|
||||
|
||||
let pk_d: Point = ivk * g_d
|
||||
|
||||
let mut note_contents: list<bool> = []
|
||||
|
||||
let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
|
||||
|
||||
let mut value_num: Num = Num.zero()
|
||||
let mut coeff: Scalar = Scalar.one()
|
||||
for bit in value_bits:
|
||||
value_num = value_num.add_bool_with_coeff(bit, coeff)
|
||||
coeff = coeff.double()
|
||||
# Is this equivalent?
|
||||
let value_num = value_bits as Num
|
||||
|
||||
note_contents.extend(value_bits)
|
||||
note_contents.extend(g_d)
|
||||
note_contents.extend(pk_d)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
let rcm: list<bool> = commitment_randomness as list<bool>
|
||||
let rcm: Point = rcm * G_NOTE_COMMIT_R
|
||||
cm += rcm
|
||||
|
||||
let mut position_bits: list<bool> = []
|
||||
let mut cur: Scalar = cm.u
|
||||
|
||||
for i, (node, is_right) in enumerate(auth_path):
|
||||
position_bits.push(is_right)
|
||||
|
||||
let node: EncryptedNum = EncryptedNum.from(node)
|
||||
print(node)
|
||||
let (left: list<bool>, right: list<bool>) = Num.swap_if(is_right, cur, node)
|
||||
|
||||
let mut preimage: list<bool> = []
|
||||
preimage.extend(left)
|
||||
preimage.extend(right)
|
||||
|
||||
cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
|
||||
let rt: Point = EncryptedNum.from(anchor)
|
||||
|
||||
enforce (cur - rt) * value_num == 0
|
||||
|
||||
let position: Point = position_bits * G_NULL
|
||||
let rho: Point = cm + position
|
||||
|
||||
nf_preimage.extend(rho)
|
||||
assert len(nf_preimage) == 512
|
||||
let nf: list<bool> = blake2s(nf_preimage, PRF_NF)
|
||||
|
||||
return (rk, cv, rt, nf)
|
||||
|
||||
def output_mint(
|
||||
value: u64,
|
||||
randomness: Scalar,
|
||||
|
||||
g_d: Point,
|
||||
|
||||
esk: Scalar,
|
||||
pk_d: Point,
|
||||
|
||||
commitment_randomness: Scalar
|
||||
) -> (Point, Point, Scalar):
|
||||
let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
|
||||
|
||||
let mut note_contents: list<bool> = []
|
||||
note_contents.extend(value_bits)
|
||||
|
||||
let g_d: Point = witness g_d
|
||||
assert is_not_small_order(g_d)
|
||||
|
||||
let esk: list<bool> = esk as list<bool>
|
||||
let epk: Point = esk * g_d
|
||||
|
||||
let v_contents: list<bool> = pk_d.v as list<bool>
|
||||
|
||||
let sign_bit: bool = pk_d.u.is_odd() as bool
|
||||
|
||||
note_contents.extend(v_contents)
|
||||
note_contents.push(sign_bit)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
|
||||
let rcm: list<bool> = commitment_randomness as list<bool>
|
||||
let rcm: Point = rcm * G_NOTE_COMMIT_R
|
||||
|
||||
cm += rcm
|
||||
|
||||
let cmu: Scalar = cm.u
|
||||
|
||||
return (cv, epk, cmu)
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
# You will need this repo:
|
||||
# https://github.com/zcash/librustzcash/
|
||||
# Then compare this code to the file:
|
||||
# librustzcash/zcash_proofs/src/circuit/sapling.rs
|
||||
|
||||
# What is the LC stuff?
|
||||
# Difference between AllocatedNum and Num
|
||||
# Why BlsScalar vs JJScalar?
|
||||
const:
|
||||
G_VCV: Point
|
||||
G_VCR: Point
|
||||
G_SPEND: Point
|
||||
G_PROOF: Point
|
||||
G_NOTE_COMMIT_R: Point
|
||||
G_NULL: Point
|
||||
|
||||
CRH_IVK: Blake2sPersonalization
|
||||
NOTE_COMMIT: PedersenPersonalization
|
||||
MERKLE: list<PedersenPersonalization>
|
||||
PRF_NF: Blake2sPersonalization
|
||||
|
||||
def value_commit(value: u64, randomness: Scalar) -> (Point, list<bool>):
|
||||
let value_bits: list<bool> = value as list<bool>
|
||||
let value: Point = value * G_VCV
|
||||
|
||||
let rcv: list<bool> = randomness as list<bool>
|
||||
let rcv: Point = rcv * G_VCR
|
||||
|
||||
let cv: Point = value + rcv
|
||||
emit cv
|
||||
return value_bits
|
||||
|
||||
# The parameters to this function are the same as in:
|
||||
# struct Spend
|
||||
proof input_burn:
|
||||
private:
|
||||
value: u64 # ValueCommitment.value
|
||||
randomness: Scalar # ValueCommitment.randomness
|
||||
|
||||
ak: Point # from ProofGenerationKey
|
||||
ar: Scalar
|
||||
|
||||
nsk: Scalar # from ProofGenerationKey
|
||||
|
||||
g_d: Point # Computed from payment_address
|
||||
|
||||
commitment_randomness: Scalar
|
||||
|
||||
auth_path: list<(Scalar, bool)>
|
||||
|
||||
anchor: Scalar
|
||||
|
||||
contract -> (Point, Point, Point, list<bool>):
|
||||
let ak = witness(ak)
|
||||
ak.assert_not_small_order()
|
||||
|
||||
let ar: list<bool> = ar as list<bool>
|
||||
let ar: Point = ar * G_SPEND
|
||||
|
||||
let rk: Point = ak + ar
|
||||
emit rk
|
||||
|
||||
let nsk: list<bool> = nsk as list<bool>
|
||||
let nk: Point = nsk * G_PROOF
|
||||
|
||||
let mut ivk_preimage: list<bool> = []
|
||||
# Must be list<bool> as well
|
||||
ivk_preimage.extend(ak.repr())
|
||||
|
||||
let mut nf_preimage: list<bool> = []
|
||||
let nk_repr: list<bool> = nk.repr()
|
||||
ivk_preimage.extend(nk_repr)
|
||||
nf_preimage.extend(nk_repr)
|
||||
|
||||
assert len(ivk_preimage) == 512
|
||||
assert len(nf_preimage) == 256
|
||||
|
||||
let mut ivk: list<bool> = blake2s(ivk_preimage, CRH_IVK)
|
||||
ivk.truncate(Scalar::CAPACITY)
|
||||
|
||||
let g_d: Point = witness g_d
|
||||
g_d.assert_not_small_order()
|
||||
|
||||
let pk_d: Point = ivk * g_d
|
||||
|
||||
let mut note_contents: list<bool> = []
|
||||
|
||||
let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
|
||||
|
||||
let mut value_num: Num = Num.zero()
|
||||
let mut coeff: Scalar = Scalar.one()
|
||||
for bit in value_bits:
|
||||
value_num = value_num.add_bool_with_coeff(bit, coeff)
|
||||
coeff = coeff.double()
|
||||
# Is this equivalent?
|
||||
let value_num = value_bits as Num
|
||||
|
||||
note_contents.extend(value_bits)
|
||||
note_contents.extend(g_d)
|
||||
note_contents.extend(pk_d)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
let rcm: list<bool> = commitment_randomness as list<bool>
|
||||
let rcm: Point = rcm * G_NOTE_COMMIT_R
|
||||
cm += rcm
|
||||
|
||||
let mut position_bits: list<bool> = []
|
||||
let mut cur: Scalar = cm.u
|
||||
|
||||
for i, (node, is_right) in enumerate(auth_path):
|
||||
position_bits.push(is_right)
|
||||
|
||||
let node: EncryptedNum = EncryptedNum.from(node)
|
||||
print(node)
|
||||
let (left: list<bool>, right: list<bool>) = Num.swap_if(is_right, cur, node)
|
||||
|
||||
let mut preimage: list<bool> = []
|
||||
preimage.extend(left)
|
||||
preimage.extend(right)
|
||||
|
||||
cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
|
||||
let rt: Point = EncryptedNum.from(anchor)
|
||||
|
||||
enforce (cur - rt) * value_num == 0
|
||||
emit rt
|
||||
|
||||
let position: Point = position_bits * G_NULL
|
||||
let rho: Point = cm + position
|
||||
|
||||
nf_preimage.extend(rho)
|
||||
assert len(nf_preimage) == 512
|
||||
let nf: list<bool> = blake2s(nf_preimage, PRF_NF)
|
||||
emit nf
|
||||
|
||||
def output_mint(
|
||||
value: u64,
|
||||
randomness: Scalar,
|
||||
|
||||
g_d: Point,
|
||||
|
||||
esk: Scalar,
|
||||
pk_d: Point,
|
||||
|
||||
commitment_randomness: Scalar
|
||||
) -> (Point, Point, Scalar):
|
||||
let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
|
||||
|
||||
let mut note_contents: list<bool> = []
|
||||
note_contents.extend(value_bits)
|
||||
|
||||
let g_d: Point = witness g_d
|
||||
assert is_not_small_order(g_d)
|
||||
|
||||
let esk: list<bool> = esk as list<bool>
|
||||
let epk: Point = esk * g_d
|
||||
|
||||
let v_contents: list<bool> = pk_d.v as list<bool>
|
||||
|
||||
let sign_bit: bool = pk_d.u.is_odd() as bool
|
||||
|
||||
note_contents.extend(v_contents)
|
||||
note_contents.push(sign_bit)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
|
||||
let rcm: list<bool> = commitment_randomness as list<bool>
|
||||
let rcm: Point = rcm * G_NOTE_COMMIT_R
|
||||
|
||||
cm += rcm
|
||||
|
||||
let cmu: Scalar = cm.u
|
||||
|
||||
return (cv, epk, cmu)
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
# You will need this repo:
|
||||
# https://github.com/zcash/librustzcash/
|
||||
# Then compare this code to the file:
|
||||
# librustzcash/zcash_proofs/src/circuit/sapling.rs
|
||||
|
||||
# What is the LC stuff?
|
||||
# Difference between AllocatedNum and Num
|
||||
# Why BlsScalar vs JJScalar?
|
||||
const:
|
||||
G_VCV: SubgroupPoint
|
||||
G_VCR: SubgroupPoint
|
||||
G_SPEND: SubgroupPoint
|
||||
G_PROOF: SubgroupPoint
|
||||
G_NOTE_COMMIT_R: SubgroupPoint
|
||||
G_NULL: SubgroupPoint
|
||||
|
||||
CRH_IVK: Blake2sPersonalization
|
||||
NOTE_COMMIT: PedersenPersonalization
|
||||
MERKLE: list<PedersenPersonalization>
|
||||
PRF_NF: Blake2sPersonalization
|
||||
|
||||
def value_commit(value: U64, randomness: Scalar) -> Binary:
|
||||
let value_bits: Binary = value as Binary
|
||||
let value: SubgroupPoint = value * G_VCV
|
||||
|
||||
let rcv: Binary = randomness as Binary
|
||||
let rcv: SubgroupPoint = rcv * G_VCR
|
||||
|
||||
let cv: SubgroupPoint = value + rcv
|
||||
emit cv
|
||||
return value_bits
|
||||
|
||||
# The parameters to this function are the same as in:
|
||||
# struct Spend
|
||||
contract input_burn(
|
||||
value: U64, # ValueCommitment.value
|
||||
randomness: Scalar, # ValueCommitment.randomness
|
||||
|
||||
ak: SubgroupPoint, # from ProofGenerationKey
|
||||
ar: Scalar,
|
||||
|
||||
nsk: Scalar, # from ProofGenerationKey
|
||||
|
||||
g_d: SubgroupPoint, # Computed from payment_address
|
||||
|
||||
commitment_randomness: Scalar,
|
||||
|
||||
auth_path: list<(Scalar, Bool)>,
|
||||
|
||||
anchor: Scalar
|
||||
) -> (SubgroupPoint, SubgroupPoint, SubgroupPoint, Binary):
|
||||
let ak = witness(ak)
|
||||
ak.assert_not_small_order()
|
||||
|
||||
let ar: Binary = ar as Binary
|
||||
let ar: SubgroupPoint = ar * G_SPEND
|
||||
|
||||
let rk: SubgroupPoint = ak + ar
|
||||
|
||||
let nsk: Binary = nsk as Binary
|
||||
let nk: SubgroupPoint = nsk * G_PROOF
|
||||
|
||||
let mut ivk_preimage: Binary = []
|
||||
# Must be Binary as well
|
||||
ivk_preimage.extend(ak.repr())
|
||||
|
||||
let mut nf_preimage: Binary = []
|
||||
let nk_repr: Binary = nk.repr()
|
||||
ivk_preimage.extend(nk_repr)
|
||||
nf_preimage.extend(nk_repr)
|
||||
|
||||
assert len(ivk_preimage) == 512
|
||||
assert len(nf_preimage) == 256
|
||||
|
||||
let mut ivk: Binary = blake2s(ivk_preimage, CRH_IVK)
|
||||
ivk.truncate(Scalar.CAPACITY)
|
||||
|
||||
let g_d: SubgroupPoint = witness g_d
|
||||
g_d.assert_not_small_order()
|
||||
|
||||
let pk_d: SubgroupPoint = ivk * g_d
|
||||
|
||||
let mut note_contents: Binary = []
|
||||
|
||||
let (cv: SubgroupPoint, value_bits: Binary) = value_commit(value, randomness)
|
||||
|
||||
let mut value_num: Num = Num.zero()
|
||||
let mut coeff: Scalar = Scalar.one()
|
||||
for bit in value_bits:
|
||||
value_num = value_num.add_Bool_with_coeff(bit, coeff)
|
||||
coeff = coeff.double()
|
||||
# Is this equivalent?
|
||||
let value_num = value_bits as Num
|
||||
|
||||
note_contents.extend(value_bits)
|
||||
note_contents.extend(g_d)
|
||||
note_contents.extend(pk_d)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: SubgroupPoint = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
let rcm: Binary = commitment_randomness as Binary
|
||||
let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
|
||||
cm += rcm
|
||||
|
||||
let mut position_bits: Binary = []
|
||||
let mut cur: Scalar = cm.u
|
||||
|
||||
for i in range(auth_path.size()):
|
||||
let (node: Scalar, is_right: Bool) = auth_path[i]
|
||||
|
||||
position_bits.push(is_right)
|
||||
|
||||
let node: EncryptedNum = EncryptedNum.from(node)
|
||||
print(node)
|
||||
let (left: Binary, right: Binary) = Num.swap_if(is_right, cur, node)
|
||||
|
||||
let mut preimage: Binary = []
|
||||
preimage.extend(left)
|
||||
preimage.extend(right)
|
||||
|
||||
cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
|
||||
let rt: SubgroupPoint = EncryptedNum.from(anchor)
|
||||
|
||||
enforce (cur - rt) * value_num == 0
|
||||
|
||||
let position: SubgroupPoint = position_bits * G_NULL
|
||||
let rho: SubgroupPoint = cm + position
|
||||
|
||||
nf_preimage.extend(rho)
|
||||
assert len(nf_preimage) == 512
|
||||
let nf: Binary = blake2s(nf_preimage, PRF_NF)
|
||||
|
||||
emit (rk, cv, rt, nf)
|
||||
|
||||
contract output_mint(
|
||||
value: U64,
|
||||
randomness: Scalar,
|
||||
|
||||
g_d: SubgroupPoint,
|
||||
|
||||
esk: Scalar,
|
||||
pk_d: SubgroupPoint,
|
||||
|
||||
commitment_randomness: Scalar
|
||||
) -> (SubgroupPoint, SubgroupPoint, Scalar):
|
||||
let value_bits: Binary = value_commit(value, randomness)
|
||||
|
||||
let mut note_contents: Binary = []
|
||||
note_contents.extend(value_bits)
|
||||
|
||||
let g_d: EdwardsPoint = witness(g_d)
|
||||
g_d.assert_not_small_order()
|
||||
|
||||
let esk: Binary = esk as Binary
|
||||
let epk: SubgroupPoint = esk * g_d
|
||||
|
||||
let v_contents: Binary = pk_d.v as Binary
|
||||
|
||||
let sign_bit: Bool = pk_d.u.is_odd() as Bool
|
||||
|
||||
note_contents.extend(v_contents)
|
||||
note_contents.push(sign_bit)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: SubgroupPoint = pedersen_hash(NOTE_COMMIT, note_contents)
|
||||
|
||||
let rcm: Binary = commitment_randomness as Binary
|
||||
let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
|
||||
|
||||
cm += rcm
|
||||
|
||||
let cmu: Scalar = cm.u
|
||||
|
||||
emit (cv, epk, cmu)
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# :set syntax=drk
|
||||
# :source ../scripts/drk.vim
|
||||
const:
|
||||
G_VCV: SubgroupPoint
|
||||
G_VCR: SubgroupPoint
|
||||
G_SPEND: SubgroupPoint
|
||||
G_PROOF: SubgroupPoint
|
||||
G_NOTE_COMMIT_R: SubgroupPoint
|
||||
G_NULL: SubgroupPoint
|
||||
|
||||
CRH_IVK: Blake2sPersonalization
|
||||
NOTE_COMMIT: PedersenPersonalization
|
||||
MERKLE: list<PedersenPersonalization>
|
||||
PRF_NF: Blake2sPersonalization
|
||||
|
||||
contract input_spend(
|
||||
value: U64 -> BinaryNumber
|
||||
randomness: Fr -> BinaryNumber
|
||||
ak: Point
|
||||
ar: Fr -> BinaryNumber
|
||||
nsk: Fr -> BinaryNumber
|
||||
g_d: Point
|
||||
commitment_randomness: Fr -> BinaryNumber
|
||||
auth_path: [(Scalar, Bool)]
|
||||
anchor: Scalar
|
||||
) -> (Point, Point, Scalar, BinaryNumber):
|
||||
let rk: Point = ak + ar * G_SPEND
|
||||
emit rk
|
||||
|
||||
let nk: Point = nsk * G_PROOF
|
||||
|
||||
let mut ivk_preimage: BinaryNumber = []
|
||||
ivk_preimage.put(ak)
|
||||
|
||||
let mut nf_preimage: BinaryNumber = []
|
||||
|
||||
ivk_preimage.put(nk)
|
||||
nf_preimage.put(nk)
|
||||
|
||||
assert ivk_preimage.len() == 512
|
||||
assert nf_preimage.len() == 256
|
||||
|
||||
let mut ivk = blake2s(ivk_preimage, CRH_IVK)
|
||||
ivk.truncate(JUBJUB_FR_CAPACITY)
|
||||
# This will error if ivk.len() != 256
|
||||
#let ivk: Fr = ivk as Fr
|
||||
let pk_d: Point = ivk * g_d
|
||||
|
||||
let cv: Point = value * G_VCV + rcv * G_VCR
|
||||
emit cv
|
||||
|
||||
let mut note_contents: BinaryNumber = []
|
||||
note_contents.put(value)
|
||||
note_contents.put(g_d)
|
||||
note_contents.put(p_k)
|
||||
assert note_contents.len() == 64 + 256 + 256
|
||||
|
||||
let mut cm = pedersen_hash(note_contents, NOTE_COMMIT)
|
||||
cm += commitment_randomness * G_NOTE_COMMIT_R
|
||||
|
||||
let mut position = []
|
||||
let mut cur: Scalar = cm.u
|
||||
|
||||
for i in range(auth_path.size()):
|
||||
let (node: Scalar, is_right: Bool) = auth_path[i]
|
||||
|
||||
position.push(is_right)
|
||||
|
||||
# Scalar -> AllocatedNum
|
||||
let (left: Scalar, right: Scalar) = swap_if(is_right, cur, node)
|
||||
|
||||
let mut preimage: BinaryNumber = []
|
||||
preimage.put(left)
|
||||
preimage.put(right)
|
||||
|
||||
cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
|
||||
enforce cur == rt
|
||||
emit rt
|
||||
|
||||
let rho: Point = rho + position * G_NULL
|
||||
|
||||
nf_preimage.put(rho)
|
||||
assert nf_preimage.len() == 512
|
||||
|
||||
let nf: BinaryNumber = blake2s(nf_preimage, PRF_NF)
|
||||
emit nf
|
||||
|
||||
contract output_mint(
|
||||
value: U64 -> BinaryNumber
|
||||
randomness: Fr -> BinaryNumber
|
||||
g_d: Point
|
||||
esk: Fr -> BinaryNumber
|
||||
pk_d: Point
|
||||
commitment_randomness: Fr -> BinaryNumber
|
||||
) -> (Point, Point, Scalar):
|
||||
let cv: Point = value * G_VCV + rcv * G_VCR
|
||||
emit cv
|
||||
|
||||
let mut note_contents: Binary = []
|
||||
note_contents.put(value)
|
||||
|
||||
let epk: Point = esk * g_d
|
||||
emit epk
|
||||
|
||||
let v_contents: Scalar = pk_d.v
|
||||
let sign_bit: Bool = pk_d.u.is_odd()
|
||||
|
||||
note_contents.put(v_contents)
|
||||
note_contents.put(sign_bit)
|
||||
|
||||
assert len(note_contents) == 64 + 256 + 256
|
||||
|
||||
let mut cm: Point = pedersen_hash(note_contents, NOTE_COMMIT)
|
||||
let rcm: Point = commitment_randomness * G_NOTE_COMMIT_R
|
||||
cm += rcm
|
||||
|
||||
let cmu: Scalar = cm.u
|
||||
emit cmu
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"constants": {
|
||||
"G_SPEND": {
|
||||
"maps_to": "zcash_proofs::constants::SPENDING_KEY_GENERATOR"
|
||||
},
|
||||
"G_VCV": {
|
||||
"maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR"
|
||||
},
|
||||
"G_VCR": {
|
||||
"maps_to": "zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR"
|
||||
},
|
||||
"CRH_IVK": {
|
||||
"maps_to": "zcash_primitives::constants::CRH_IVK_PERSONALIZATION"
|
||||
},
|
||||
"JUBJUB_FR_CAPACITY": {
|
||||
"maps_to": "jubjub::Fr::CAPACITY as usize"
|
||||
},
|
||||
"NOTE_COMMIT": {
|
||||
"maps_to": "pedersen_hash::Personalization::NoteCommitment"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# :set syntax=pism
|
||||
# :source ../scripts/pism.vim
|
||||
constant G_SPEND FixedGenerator
|
||||
constant CRH_IVK BlakePersonalization
|
||||
constant JUBJUB_FR_CAPACITY BinarySize
|
||||
constant NOTE_COMMIT PedersenPersonalization
|
||||
|
||||
contract input_spend
|
||||
param secret Fr
|
||||
param ak Point
|
||||
param value U64
|
||||
param is_cool Bool
|
||||
param path Scalar
|
||||
start
|
||||
# Compute P = xG + A
|
||||
witness ak param:ak
|
||||
assert_not_small_order ak
|
||||
fr_as_binary_le secret param:secret
|
||||
|
||||
ec_mul_const public secret G_SPEND
|
||||
|
||||
ec_add public public ak
|
||||
emit_ec public
|
||||
|
||||
# Make some a blake2s hash
|
||||
alloc_binary preimage
|
||||
ec_repr repr_ak ak
|
||||
binary_extend preimage repr_ak
|
||||
static_assert_binary_size preimage 256
|
||||
blake2s ivk preimage CRH_IVK
|
||||
emit_binary ivk
|
||||
|
||||
# Below lines are random garbage
|
||||
# Uncomment them to test
|
||||
|
||||
#binary_clone ivk2 ivk
|
||||
#binary_truncate ivk2 JUBJUB_FR_CAPACITY
|
||||
#u64_as_binary_le value_bits param:value
|
||||
#ec_mul pk_d value_bits public
|
||||
|
||||
#pedersen_hash cm ivk NOTE_COMMIT
|
||||
#ec_get_u cur cm
|
||||
#
|
||||
#alloc_bit is_cool param:is_cool
|
||||
#clone_bit is_cool2 is_cool
|
||||
#binary_push ivk is_cool2
|
||||
|
||||
#alloc_scalar path param:path
|
||||
#conditionally_reverse ul ur cur path is_cool
|
||||
|
||||
#scalar_as_binary ul_bin ul
|
||||
#binary_extend preimage ul_bin
|
||||
|
||||
#scalar_enforce_equal ur ul
|
||||
#emit_scalar ur
|
||||
end
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
const G_SPEND: SubgroupPoint
|
||||
|
||||
contract input_spend(
|
||||
secret: Fr -> BinaryNumber
|
||||
) -> Point:
|
||||
let public: Point = secret * G_SPEND
|
||||
emit public
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
# :set syntax=pism
|
||||
# :source ../scripts/pism.vim
|
||||
constant G_SPEND FixedGenerator
|
||||
constant CRH_IVK BlakePersonalization
|
||||
constant JUBJUB_FR_CAPACITY BinarySize
|
||||
constant NOTE_COMMIT PedersenPersonalization
|
||||
|
||||
contract input_spend
|
||||
param secret Fr
|
||||
param ak Point
|
||||
param value U64
|
||||
param is_cool Bool
|
||||
param path Scalar
|
||||
{% for n in range(10) %}
|
||||
param path_{{ n }} Scalar
|
||||
param is_right_{{ n }} Bool
|
||||
{% endfor %}
|
||||
start
|
||||
# Compute P = xG + A
|
||||
witness ak param:ak
|
||||
assert_not_small_order ak
|
||||
fr_as_binary_le secret param:secret
|
||||
|
||||
ec_mul_const public secret G_SPEND
|
||||
|
||||
ec_add public public ak
|
||||
emit_ec public
|
||||
|
||||
# Make some a blake2s hash
|
||||
alloc_binary preimage
|
||||
ec_repr repr_ak ak
|
||||
binary_extend preimage repr_ak
|
||||
static_assert_binary_size preimage 256
|
||||
blake2s ivk preimage CRH_IVK
|
||||
emit_binary ivk
|
||||
|
||||
############
|
||||
# For loop 10 times
|
||||
{% for n in range(10) %}
|
||||
alloc_bit is_right param:is_right_{{ n }}
|
||||
alloc_scalar path param:path_{{ n }}
|
||||
{% endfor %}
|
||||
############
|
||||
|
||||
# Below lines are random garbage
|
||||
# Uncomment them to test
|
||||
|
||||
#binary_clone ivk2 ivk
|
||||
#binary_truncate ivk2 JUBJUB_FR_CAPACITY
|
||||
#u64_as_binary_le value_bits param:value
|
||||
#ec_mul pk_d value_bits public
|
||||
|
||||
#pedersen_hash cm ivk NOTE_COMMIT
|
||||
#ec_get_u cur cm
|
||||
#
|
||||
#alloc_bit is_cool param:is_cool
|
||||
#clone_bit is_cool2 is_cool
|
||||
#binary_push ivk is_cool2
|
||||
|
||||
#alloc_scalar path param:path
|
||||
#conditionally_reverse ul ur cur path is_cool
|
||||
|
||||
#scalar_as_binary ul_bin ul
|
||||
#binary_extend preimage ul_bin
|
||||
|
||||
#scalar_enforce_equal ur ul
|
||||
#emit_scalar ur
|
||||
end
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
# :set syntax=pism
|
||||
# :source ../scripts/pism.vim
|
||||
constant G_VCV FixedGenerator
|
||||
constant G_VCR FixedGenerator
|
||||
constant G_SPEND FixedGenerator
|
||||
constant G_PROOF FixedGenerator
|
||||
constant G_NOTE_COMMIT_R FixedGenerator
|
||||
constant G_NULL FixedGenerator
|
||||
constant CRH_IVK BlakePersonalization
|
||||
constant NOTE_COMMIT PedersenPersonalization
|
||||
constant MERKLE_0 PedersenPersonalization
|
||||
constant MERKLE_1 PedersenPersonalization
|
||||
constant MERKLE_2 PedersenPersonalization
|
||||
constant MERKLE_3 PedersenPersonalization
|
||||
# ...
|
||||
constant PRF_NF BlakePersonalization
|
||||
constant JUBJUB_FR_CAPACITY ByteSize
|
||||
|
||||
contract input_spend
|
||||
param secret Fr
|
||||
|
||||
param value U64
|
||||
param randomness Fr
|
||||
param ak Point
|
||||
param ar Fr
|
||||
param nsk Fr
|
||||
param g_d Point
|
||||
param commitment_randomness Fr
|
||||
param auth_path_0_0 Scalar
|
||||
param auth_path_0_1 Bool
|
||||
param auth_path_1_0 Scalar
|
||||
param auth_path_1_1 Bool
|
||||
# ...
|
||||
param anchor Scalar
|
||||
start
|
||||
# let rk: Point = ak + ar * G_SPEND
|
||||
witness ak param:ak
|
||||
assert_not_small_order ak
|
||||
fr_as_binary_le ar param:ar
|
||||
ec_mul_const ar ar G_SPEND
|
||||
ec_add rk ak ar
|
||||
# emit rk
|
||||
emit_ec rk
|
||||
|
||||
# let nk: Point = nsk * G_PROOF
|
||||
fr_as_binary_le nsk param:nsk
|
||||
ec_mul_const nk nsk G_PROOF
|
||||
|
||||
# let mut ivk_preimage: BinaryNumber = []
|
||||
alloc_binary ivk_preimage
|
||||
# ivk_preimage.put(ak)
|
||||
ec_repr repr_ak ak
|
||||
binary_extend ivk_preimage repr_ak
|
||||
|
||||
# let mut nf_preimage: BinaryNumber = []
|
||||
alloc_binary nf_preimage
|
||||
ec_repr repr_nk nk
|
||||
binary_clone repr_nk2 repr_nk
|
||||
# ivk_preimage.put(nk)
|
||||
binary_extend ivk_preimage repr_nk
|
||||
# nf_preimage.put(nk)
|
||||
binary_extend ivk_preimage repr_nk2
|
||||
|
||||
# assert ivk_preimage.len() == 512
|
||||
static_assert_binary_size ivk_preimage 512
|
||||
# assert nf_preimage.len() == 256
|
||||
static_assert_binary_size nf_preimage 256
|
||||
|
||||
# let mut ivk = blake2s(ivk_preimage, CRH_IVK)
|
||||
blake2s ivk ivk_preimage CRH_IVK
|
||||
# ivk.truncate(JUBJUB_FR_CAPACITY)
|
||||
binary_truncate ivk JUBJUB_FR_CAPACITY
|
||||
|
||||
# let pk_d: Point = ivk * g_d
|
||||
witness g_d param:g_d
|
||||
assert_not_small_order g_d
|
||||
ec_mul pk_d ivk g_d
|
||||
|
||||
# let cv: Point = value * G_VCV + rcv * G_VCR
|
||||
u64_as_binary_le value_bits param:value
|
||||
ec_mul_const value value_bits G_VCV
|
||||
fr_as_binary_le rcv param:randomness
|
||||
ec_mul_const rcv rcv G_VCR
|
||||
ec_add cv value rcv
|
||||
# emit cv
|
||||
emit_ec cv
|
||||
|
||||
# let mut note_contents: BinaryNumber = []
|
||||
alloc_binary note_contents
|
||||
|
||||
# note_contents.put(value)
|
||||
binary_extend note_contents value
|
||||
# note_contents.put(g_d)
|
||||
ec_repr repr_g_d g_d
|
||||
binary_extend note_contents repr_g_d
|
||||
# note_contents.put(p_k)
|
||||
ec_repr repr_p_k p_k
|
||||
binary_extend note_contents repr_p_k
|
||||
# assert note_contents.len() == 64 + 256 + 256
|
||||
static_assert_binary_size ivk_preimage 576
|
||||
|
||||
# let mut cm = pedersen_hash(note_contents, NOTE_COMMIT)
|
||||
pedersen_hash cm note_contents NOTE_COMMIT
|
||||
# cm += commitment_randomness * G_NOTE_COMMIT_R
|
||||
fr_as_binary_le rcm param:commitment_randomness
|
||||
ec_mul_const cm1 rcm G_NOTE_COMMIT_R
|
||||
ec_add cm cm cm1
|
||||
|
||||
# let mut position = []
|
||||
alloc_binary position
|
||||
# let mut cur: Scalar = cm.u
|
||||
ec_get_u cur cm
|
||||
|
||||
###############################################
|
||||
# There are no loops in this language.
|
||||
# ZK proofs must have a fixed size.
|
||||
# So in this assembly we UNROLL all loops.
|
||||
# for i in range(auth_path.size()):
|
||||
#
|
||||
# Here we give the example of loop 0.
|
||||
# Replace the indexes with the value i
|
||||
# Below line is auth_path[0].1
|
||||
|
||||
# let (node: Scalar, is_right: Bool) = auth_path[i]
|
||||
# position.push(is_right)
|
||||
alloc_bit cur_is_right param:auth_path_0_1
|
||||
clone_bit cur_is_right2 cur_is_right
|
||||
binary_push position cur_is_right2
|
||||
alloc_num path_element param:auth_path_0_0
|
||||
# let (left: Scalar, right: Scalar) = swap_if(is_right, cur, node)
|
||||
conditionally_reverse ul ur cur path_element is_right
|
||||
# let mut preimage: BinaryNumber = []
|
||||
alloc_binary preimage
|
||||
# preimage.put(left)
|
||||
num_to_binary ul_bits ul
|
||||
binary_extend preimage ul_bits
|
||||
# preimage.put(right)
|
||||
num_to_binary ur_bits ur
|
||||
binary_extend preimage ur_bits
|
||||
# cur = pedersen_hash(MERKLE_TREE[i], preimage).u
|
||||
pedersen_hash curhash preimage MERKLE_0
|
||||
ec_get_u cur curhash
|
||||
# ... repeat the above N times
|
||||
###############################################
|
||||
|
||||
# enforce cur == rt
|
||||
alloc_num rt param:anchor
|
||||
num_enforce_equal cur rt
|
||||
# emit rt
|
||||
emit_num rt
|
||||
|
||||
# let rho: Point = rho + position * G_NULL
|
||||
ec_mul_const position position_bits G_NULL
|
||||
ec_add rho rho position
|
||||
# nf_preimage.put(rho)
|
||||
ec_repr repr_rho rho
|
||||
binary_extend nf_preimage repr_rho
|
||||
# assert nf_preimage.len() == 512
|
||||
static_assert_binary_size nf_preimage 512
|
||||
|
||||
# let nf: BinaryNumber = blake2s(nf_preimage, PRF_NF)
|
||||
blake2s nf nf_preimage PRF_NF
|
||||
emit_binary nf
|
||||
end
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
constant G_VCV FixedGenerator
|
||||
constant G_VCR FixedGenerator
|
||||
constant G_SPEND FixedGenerator
|
||||
constant PRF_NF BlakePersonalization
|
||||
constant CRH_IVK BlakePersonalization
|
||||
constant NOTE_COMMIT PedersenPersonalization
|
||||
{% for i in range(32) %}
|
||||
constant MERKLE_{{ i }} PedersenPersonalization
|
||||
{% endfor %}
|
||||
|
||||
contract spend_contract
|
||||
# Value commitment
|
||||
param value U64
|
||||
param asset_id Fr
|
||||
param randomness_value Fr
|
||||
param randomness_asset Fr
|
||||
|
||||
param serial Fr
|
||||
param randomness_coin Fr
|
||||
param secret Fr
|
||||
param signature_secret Fr
|
||||
|
||||
{% for i in range(32) %}
|
||||
param branch_{{ i }} Scalar
|
||||
param is_right_{{ i }} Bool
|
||||
{% endfor %}
|
||||
start
|
||||
# Witness input values
|
||||
u64_as_binary_le value param:value
|
||||
fr_as_binary_le asset_id param:asset_id
|
||||
fr_as_binary_le randomness_value param:randomness_value
|
||||
fr_as_binary_le randomness_asset param:randomness_asset
|
||||
|
||||
# Make value commitment
|
||||
# V = v * G_VCV + r * G_VCR
|
||||
|
||||
ec_mul_const vcv value G_VCV
|
||||
ec_mul_const rcv randomness_value G_VCR
|
||||
ec_add cv vcv rcv
|
||||
# emit cv
|
||||
emit_ec cv
|
||||
|
||||
# Make asset_id commitment
|
||||
# A = a * G_VCV + r * G_VCR
|
||||
|
||||
ec_mul_const vca asset_id G_VCV
|
||||
ec_mul_const rca randomness_asset G_VCR
|
||||
ec_add ca vca rca
|
||||
# emit ca
|
||||
emit_ec ca
|
||||
|
||||
# Make the nullifier
|
||||
# N = Hash(secret, serial)
|
||||
fr_as_binary_le serial param:serial
|
||||
fr_as_binary_le secret param:secret
|
||||
|
||||
alloc_binary nf_preimage
|
||||
|
||||
# Fr values are 252 bits so we need to pad it with extra 0s
|
||||
# to match the Rust values which are 256 bits
|
||||
{% macro binary_put_fr(binary, var) -%}
|
||||
binary_extend {{ binary }} {{ var }}
|
||||
{% for n in range(4) %}
|
||||
alloc_const_bit zero_bit false
|
||||
binary_push {{ binary }} zero_bit
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
# secret
|
||||
binary_clone secret2 secret
|
||||
{{ binary_put_fr("nf_preimage", "secret2") }}
|
||||
|
||||
# serial
|
||||
binary_clone serial2 serial
|
||||
{{ binary_put_fr("nf_preimage", "serial2") }}
|
||||
|
||||
# Secret: Fr = 252 + 4 bits padding
|
||||
# Serial: Fr = 252 + 4 bits padding
|
||||
# TOTAL: 512 bits for preimage
|
||||
static_assert_binary_size nf_preimage 512
|
||||
blake2s nf nf_preimage PRF_NF
|
||||
emit_binary nf
|
||||
|
||||
# Derive the public key
|
||||
# P = secret * G
|
||||
ec_mul_const public secret G_SPEND
|
||||
|
||||
# Make the coin (same as mint contract)
|
||||
# C = Hash(public_key, value, asset_id, serial, randomness_coin)
|
||||
fr_as_binary_le randomness_coin param:randomness_coin
|
||||
|
||||
# Build the preimage to hash
|
||||
alloc_binary preimage
|
||||
|
||||
# public_key
|
||||
ec_repr repr_public public
|
||||
binary_extend preimage repr_public
|
||||
|
||||
# value
|
||||
binary_extend preimage value
|
||||
|
||||
# serial
|
||||
{{ binary_put_fr("preimage", "serial") }}
|
||||
|
||||
# randomness_coin
|
||||
{{ binary_put_fr("preimage", "randomness_coin") }}
|
||||
|
||||
# asset_id
|
||||
{{ binary_put_fr("preimage", "asset_id") }}
|
||||
|
||||
# Public key: SubgroupPoint = 256 bits
|
||||
# Value: u64 = 64 bits
|
||||
# AssetID: Fr = 252 + 4 bits padding
|
||||
# Serial: Fr = 252 + 4 bits padding
|
||||
# Randomness coin Fr = 252 + 4 bits padding
|
||||
# TOTAL: 1088 bits for preimage
|
||||
static_assert_binary_size preimage 1088
|
||||
blake2s coin preimage CRH_IVK
|
||||
# Debug stuff. Normally we don't reveal the coin in the spend proof.
|
||||
#binary_clone coin2 coin
|
||||
#emit_binary coin2
|
||||
|
||||
# coin_commit = PedersenHash(coin)
|
||||
pedersen_hash cm coin NOTE_COMMIT
|
||||
# left = coin_commit.u
|
||||
ec_get_u current cm
|
||||
|
||||
# Our merkle tree has a height of 32
|
||||
{% for i in range(32) %}
|
||||
# left = current
|
||||
# right = branch[{{ i }}]
|
||||
alloc_scalar branch param:branch_{{ i }}
|
||||
|
||||
# is_right = is_right[{{ i }}]
|
||||
alloc_bit is_right param:is_right_{{ i }}
|
||||
|
||||
# reverse(a, b, condition) = if condition (b, a) else (a, b)
|
||||
conditionally_reverse left right current branch is_right
|
||||
|
||||
# coin_commit = PedersenHash(left || right)
|
||||
scalar_as_binary left left
|
||||
scalar_as_binary right right
|
||||
alloc_binary preimage
|
||||
binary_extend preimage left
|
||||
binary_extend preimage right
|
||||
pedersen_hash cm preimage MERKLE_{{ i }}
|
||||
# current = coin_commit.u
|
||||
ec_get_u current cm
|
||||
{% endfor %}
|
||||
# Reveal the merkle root
|
||||
emit_scalar current
|
||||
|
||||
# Emit the signature public key
|
||||
fr_as_binary_le signature_secret param:signature_secret
|
||||
ec_mul_const signature_public signature_secret G_SPEND
|
||||
emit_ec signature_public
|
||||
end
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
constant one 0x0000000000000000000000000000000000000000000000000000000000000001
|
||||
|
||||
contract tutorial_contract
|
||||
param w
|
||||
param a
|
||||
param b
|
||||
|
||||
private m
|
||||
set m a
|
||||
mul m b
|
||||
|
||||
# ab = m
|
||||
lc0_add a
|
||||
lc1_add b
|
||||
lc2_add m
|
||||
enforce
|
||||
|
||||
# v = wab ...
|
||||
public v
|
||||
set v w
|
||||
mul v a
|
||||
mul v b
|
||||
|
||||
# v = wab + a + b ...
|
||||
add v a
|
||||
add v b
|
||||
|
||||
# v = wab + a + b - v'
|
||||
# v' = w(a + b)
|
||||
local vprime
|
||||
set vprime a
|
||||
add vprime b
|
||||
mul vprime w
|
||||
sub v vprime
|
||||
|
||||
# w(m - a - b) = v - a - b
|
||||
lc0_add w
|
||||
lc1_add m
|
||||
lc1_sub a
|
||||
lc1_sub b
|
||||
lc2_add v
|
||||
lc2_sub a
|
||||
lc2_sub b
|
||||
enforce
|
||||
|
||||
# Binary check that w^2 = w
|
||||
lc0_add w
|
||||
lc1_add w
|
||||
lc2_add w
|
||||
enforce
|
||||
end
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
constant v 123
|
||||
|
||||
contract input_spend
|
||||
param x
|
||||
private x2
|
||||
set x2 x
|
||||
mul x2 x
|
||||
|
||||
lc0_add x
|
||||
lc1_add x
|
||||
lc2_add x2
|
||||
enforce
|
||||
|
||||
private x3
|
||||
set x3 x2
|
||||
mul x3 x
|
||||
|
||||
lc0_add x2
|
||||
lc1_add x
|
||||
lc2_add x3
|
||||
enforce
|
||||
|
||||
public input
|
||||
set input x3
|
||||
|
||||
lc0_add input
|
||||
lc1_add_one
|
||||
lc2_add x3
|
||||
enforce
|
||||
end
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
# Functions here are called from pism.py using getattr()
|
||||
# and the function name as a string.
|
||||
|
||||
def witness(line, out, point):
|
||||
return \
|
||||
r"""let %s = ecc::EdwardsPoint::witness(
|
||||
cs.namespace(|| "%s"),
|
||||
%s.map(jubjub::ExtendedPoint::from))?;""" % (out, line, point)
|
||||
|
||||
def assert_not_small_order(line, point):
|
||||
return '%s.assert_not_small_order(cs.namespace(|| "%s"))?;' % (point, line)
|
||||
|
||||
def u64_as_binary_le(line, out, val):
|
||||
return \
|
||||
r"""let %s = boolean::u64_into_boolean_vec_le(
|
||||
cs.namespace(|| "%s"),
|
||||
%s,
|
||||
)?;""" % (out, line, val)
|
||||
|
||||
def fr_as_binary_le(line, out, fr):
|
||||
return \
|
||||
r"""let %s = boolean::field_into_boolean_vec_le(
|
||||
cs.namespace(|| "%s"), %s)?;""" % (out, line, fr)
|
||||
|
||||
def ec_mul_const(line, out, fr, base):
|
||||
return \
|
||||
r"""let %s = ecc::fixed_base_multiplication(
|
||||
cs.namespace(|| "%s"),
|
||||
&%s,
|
||||
&%s,
|
||||
)?;""" % (out, line, base, fr)
|
||||
|
||||
def ec_mul(line, out, fr, base):
|
||||
return 'let %s = %s.mul(cs.namespace(|| "%s"), &%s)?;' % (
|
||||
out, base, line, fr)
|
||||
|
||||
def ec_add(line, out, a, b):
|
||||
return 'let %s = %s.add(cs.namespace(|| "%s"), &%s)?;' % (out, a, line, b)
|
||||
|
||||
def ec_repr(line, out, point):
|
||||
return 'let %s = %s.repr(cs.namespace(|| "%s"))?;' % (out, point, line)
|
||||
|
||||
def ec_get_u(line, out, point):
|
||||
return "let mut %s = %s.get_u().clone();" % (out, point)
|
||||
|
||||
def emit_ec(line, point):
|
||||
return '%s.inputize(cs.namespace(|| "%s"))?;' % (point, line)
|
||||
|
||||
def alloc_binary(line, out):
|
||||
return "let mut %s = vec![];" % out
|
||||
|
||||
def binary_clone(line, out, binary):
|
||||
return "let mut %s: Vec<_> = %s.iter().cloned().collect();" % (out, binary)
|
||||
|
||||
def binary_extend(line, binary, value):
|
||||
return "%s.extend(%s);" % (binary, value)
|
||||
|
||||
def binary_push(line, binary, bit):
|
||||
return "%s.push(%s);" % (binary, bit)
|
||||
|
||||
def binary_truncate(line, binary, size):
|
||||
return "%s.truncate(%s);" % (binary, size)
|
||||
|
||||
def static_assert_binary_size(line, binary, size):
|
||||
return "assert_eq!(%s.len(), %s);" % (binary, size)
|
||||
|
||||
def blake2s(line, out, input, personalization):
|
||||
return \
|
||||
r"""let mut %s = blake2s::blake2s(
|
||||
cs.namespace(|| "%s"),
|
||||
&%s,
|
||||
%s,
|
||||
)?;""" % (out, line, input, personalization)
|
||||
|
||||
def pedersen_hash(line, out, input, personalization):
|
||||
return \
|
||||
r"""let mut %s = pedersen_hash::pedersen_hash(
|
||||
cs.namespace(|| "%s"),
|
||||
%s,
|
||||
&%s,
|
||||
)?;""" % (out, line, personalization, input)
|
||||
|
||||
def emit_binary(line, binary):
|
||||
return 'multipack::pack_into_inputs(cs.namespace(|| "%s"), &%s)?;' % (
|
||||
line, binary)
|
||||
|
||||
def alloc_bit(line, out, value):
|
||||
return \
|
||||
r"""let %s = boolean::Boolean::from(boolean::AllocatedBit::alloc(
|
||||
cs.namespace(|| "%s"),
|
||||
%s
|
||||
)?);""" % (out, line, value)
|
||||
|
||||
def alloc_const_bit(line, out, value):
|
||||
return "let %s = Boolean::constant(%s);" % (out, value)
|
||||
|
||||
def clone_bit(line, out, value):
|
||||
return "let %s = %s.clone();" % (out, value)
|
||||
|
||||
def alloc_scalar(line, out, scalar):
|
||||
return \
|
||||
r"""let %s =
|
||||
num::AllocatedNum::alloc(cs.namespace(|| "%s"), || Ok(*%s.get()?))?;""" % (
|
||||
out, line, scalar)
|
||||
|
||||
def scalar_as_binary(line, out, scalar):
|
||||
return 'let %s = %s.to_bits_le(cs.namespace(|| "%s"))?;' % (out, scalar,
|
||||
line)
|
||||
|
||||
def emit_scalar(line, scalar):
|
||||
return '%s.inputize(cs.namespace(|| "%s"))?;' % (scalar, line)
|
||||
|
||||
def scalar_enforce_equal(line, scalar_left, scalar_right):
|
||||
return \
|
||||
r"""cs.enforce(
|
||||
|| "%s",
|
||||
|lc| lc + %s.get_variable(),
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + %s.get_variable(),
|
||||
);""" % (line, scalar_left, scalar_right)
|
||||
|
||||
def conditionally_reverse(line, out_left, out_right, in_left, in_right,
|
||||
condition):
|
||||
return \
|
||||
r"""let (%s, %s) = num::AllocatedNum::conditionally_reverse(
|
||||
cs.namespace(|| "%s"),
|
||||
&%s,
|
||||
&%s,
|
||||
&%s,
|
||||
)?;""" % (out_left, out_right, line, in_left, in_right, condition)
|
||||
|
||||
@@ -1,460 +0,0 @@
|
||||
import argparse
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
alloc_commands = {
|
||||
"param": 1,
|
||||
"private": 1,
|
||||
"public": 1,
|
||||
}
|
||||
|
||||
op_commands = {
|
||||
"set": 2,
|
||||
"mul": 2,
|
||||
"add": 2,
|
||||
"sub": 2,
|
||||
"divide": 2,
|
||||
"double": 1,
|
||||
"square": 1,
|
||||
"invert": 1,
|
||||
"unpack_bits": 3,
|
||||
"load": 2,
|
||||
"local": 1,
|
||||
"debug": 1,
|
||||
"dump_alloc": 0,
|
||||
"dump_local": 0,
|
||||
}
|
||||
|
||||
constraint_commands = {
|
||||
"lc0_add": 1,
|
||||
"lc1_add": 1,
|
||||
"lc2_add": 1,
|
||||
"lc0_sub": 1,
|
||||
"lc1_sub": 1,
|
||||
"lc2_sub": 1,
|
||||
"lc0_add_one": 0,
|
||||
"lc1_add_one": 0,
|
||||
"lc2_add_one": 0,
|
||||
"lc0_sub_one": 0,
|
||||
"lc1_sub_one": 0,
|
||||
"lc2_sub_one": 0,
|
||||
"lc0_add_coeff": 2,
|
||||
"lc1_add_coeff": 2,
|
||||
"lc2_add_coeff": 2,
|
||||
"lc0_add_constant": 1,
|
||||
"lc1_add_constant": 1,
|
||||
"lc2_add_constant": 1,
|
||||
"enforce": 0,
|
||||
"lc_coeff_reset": 0,
|
||||
"lc_coeff_double": 0,
|
||||
}
|
||||
|
||||
def eprint(*args):
|
||||
print(*args, file=sys.stderr)
|
||||
|
||||
class Line:
|
||||
|
||||
def __init__(self, text, line_number):
|
||||
self.text = text
|
||||
self.orig = text
|
||||
self.lineno = line_number
|
||||
|
||||
self.clean()
|
||||
|
||||
def clean(self):
|
||||
# Remove the comments
|
||||
self.text = self.text.split("#", 1)[0]
|
||||
# Remove whitespace
|
||||
self.text = self.text.strip()
|
||||
|
||||
def is_empty(self):
|
||||
return bool(self.text)
|
||||
|
||||
def __repr__(self):
|
||||
return "Line %s: %s" % (self.lineno, self.orig.lstrip())
|
||||
|
||||
def command(self):
|
||||
if not self.is_empty():
|
||||
return None
|
||||
return self.text.split(" ")[0]
|
||||
|
||||
def args(self):
|
||||
if not self.is_empty():
|
||||
return None
|
||||
return self.text.split()[1:]
|
||||
|
||||
def clean(contents):
|
||||
# Split input into lines
|
||||
contents = contents.split("\n")
|
||||
contents = [Line(line, i + 1) for i, line in enumerate(contents)]
|
||||
# Remove empty blank lines
|
||||
contents = [line for line in contents if line.is_empty()]
|
||||
return contents
|
||||
|
||||
def divide_sections(contents):
|
||||
state = "NOSCOPE"
|
||||
segments = {}
|
||||
current_segment = []
|
||||
contract_name = None
|
||||
|
||||
for line in contents:
|
||||
if line.command() == "contract":
|
||||
if len(line.args()) != 1:
|
||||
eprint("error: missing contract name")
|
||||
eprint(line)
|
||||
return None
|
||||
contract_name = line.args()[0]
|
||||
|
||||
if state == "NOSCOPE":
|
||||
assert not current_segment
|
||||
state = "INSCOPE"
|
||||
continue
|
||||
else:
|
||||
assert state == "INSCOPE"
|
||||
eprint("error: double contract entry violation")
|
||||
eprint(line)
|
||||
return None
|
||||
elif line.command() == "end":
|
||||
if len(line.args()) != 0:
|
||||
eprint("error: end takes no args")
|
||||
eprint(line)
|
||||
return None
|
||||
|
||||
if state == "NOSCOPE":
|
||||
eprint("error: missing contract start for end")
|
||||
eprint(line)
|
||||
return None
|
||||
else:
|
||||
assert state == "INSCOPE"
|
||||
state = "NOSCOPE"
|
||||
segments[contract_name] = current_segment
|
||||
current_segment = []
|
||||
continue
|
||||
elif state == "NOSCOPE":
|
||||
# Ignore lines outside any contract
|
||||
continue
|
||||
|
||||
current_segment.append(line)
|
||||
|
||||
if state != "NOSCOPE":
|
||||
eprint("error: reached end of file with unclosed scope")
|
||||
return None
|
||||
|
||||
return segments
|
||||
|
||||
def extract_relevant_lines(contract, commands_table):
|
||||
relevant_lines = []
|
||||
|
||||
for line in contract:
|
||||
command = line.command()
|
||||
|
||||
if command not in commands_table.keys():
|
||||
continue
|
||||
|
||||
define = commands_table[command]
|
||||
|
||||
if len(line.args()) != define:
|
||||
eprint("error: wrong number of args")
|
||||
return None
|
||||
|
||||
relevant_lines.append(line)
|
||||
|
||||
return relevant_lines
|
||||
|
||||
class VariableType(Enum):
|
||||
PUBLIC = 1
|
||||
PRIVATE = 2
|
||||
|
||||
class Variable:
|
||||
|
||||
def __init__(self, symbol, index, type, is_param):
|
||||
self.symbol = symbol
|
||||
self.index = index
|
||||
self.type = type
|
||||
self.is_param = is_param
|
||||
|
||||
def __repr__(self):
|
||||
return "<Variable %s:%s>" % (self.symbol, self.index)
|
||||
|
||||
def generate_alloc_table(contract):
|
||||
relevant_lines = extract_relevant_lines(contract, alloc_commands)
|
||||
alloc_table = {}
|
||||
for i, line in enumerate(relevant_lines):
|
||||
assert len(line.args()) == 1
|
||||
symbol = line.args()[0]
|
||||
|
||||
command = line.command()
|
||||
|
||||
if command == "param":
|
||||
type = VariableType.PRIVATE
|
||||
is_param = True
|
||||
elif command == "private":
|
||||
type = VariableType.PRIVATE
|
||||
is_param = False
|
||||
elif command == "public":
|
||||
type = VariableType.PUBLIC
|
||||
is_param = False
|
||||
else:
|
||||
assert False
|
||||
|
||||
if symbol in alloc_table:
|
||||
eprint("error: duplicate symbol '%s'" % symbol)
|
||||
eprint(line)
|
||||
return None
|
||||
|
||||
alloc_table[symbol] = Variable(symbol, i, type, is_param)
|
||||
|
||||
return alloc_table
|
||||
|
||||
class Operation:
|
||||
|
||||
def __init__(self, line, indexes):
|
||||
self.command = line.command()
|
||||
self.args = indexes
|
||||
self.line = line
|
||||
|
||||
class VariableRefType(Enum):
|
||||
AUX = 1
|
||||
LOCAL = 2
|
||||
CONST = 3
|
||||
|
||||
class VariableRef:
|
||||
|
||||
def __init__(self, type, index):
|
||||
self.type = type
|
||||
self.index = index
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.type.name, self.index)
|
||||
|
||||
def symbols_list_to_refs(line, alloc, local_vars, constants):
|
||||
indexes = []
|
||||
for symbol in line.args():
|
||||
if symbol in alloc:
|
||||
# Lookup variable index
|
||||
index = alloc[symbol].index
|
||||
index = VariableRef(VariableRefType.AUX, index)
|
||||
elif symbol in local_vars:
|
||||
index = local_vars[symbol]
|
||||
index = VariableRef(VariableRefType.LOCAL, index)
|
||||
elif symbol in constants:
|
||||
index = constants[symbol][0]
|
||||
index = VariableRef(VariableRefType.CONST, index)
|
||||
else:
|
||||
eprint("error: missing unallocated symbol '%s'" % symbol)
|
||||
eprint(line)
|
||||
return None
|
||||
indexes.append(index)
|
||||
return indexes
|
||||
|
||||
def generate_ops_table(contract, alloc, constants):
|
||||
relevant_lines = extract_relevant_lines(contract, op_commands)
|
||||
ops = []
|
||||
local_vars = {}
|
||||
for line in relevant_lines:
|
||||
# This is a special case which creates a new local stack value
|
||||
if line.command() == "local":
|
||||
assert len(line.args()) == 1
|
||||
symbol = line.args()[0]
|
||||
local_vars[symbol] = len(local_vars)
|
||||
indexes = []
|
||||
else:
|
||||
if (indexes := symbols_list_to_refs(line, alloc,
|
||||
local_vars, constants)) is None:
|
||||
return None
|
||||
|
||||
# Handle this here directly since only the
|
||||
# load command deals with constants
|
||||
if line.command() == "load":
|
||||
assert len(indexes) == 2
|
||||
# This is the only command which uses consts
|
||||
if indexes[1].type != VariableRefType.CONST:
|
||||
eprint("error: load command takes a const argument")
|
||||
eprint(line)
|
||||
return None
|
||||
elif any(index.type == VariableRefType.CONST for index in indexes):
|
||||
eprint("error: invalid const arg")
|
||||
eprint(line)
|
||||
return None
|
||||
|
||||
ops.append(Operation(line, indexes))
|
||||
return ops
|
||||
|
||||
class Constraint:
|
||||
|
||||
def __init__(self, line, lcargs):
|
||||
self.command = line.command()
|
||||
self.args = lcargs
|
||||
self.line = line
|
||||
|
||||
def args_comment(self):
|
||||
return ", ".join("%s" % symbol for symbol in self.line.args())
|
||||
|
||||
def symbols_list_to_lcargs(line, alloc, constants):
|
||||
lcargs = []
|
||||
for symbol in line.args():
|
||||
if symbol in alloc:
|
||||
# Lookup variable index
|
||||
index = alloc[symbol].index
|
||||
lcargs.append(index)
|
||||
elif symbol in constants:
|
||||
value = constants[symbol]
|
||||
lcargs.append(value)
|
||||
else:
|
||||
eprint("error: missing unallocated symbol '%s'" % symbol)
|
||||
eprint(line)
|
||||
return None
|
||||
return lcargs
|
||||
|
||||
def generate_constraints_table(contract, alloc, constants):
|
||||
relevant_lines = extract_relevant_lines(contract, constraint_commands)
|
||||
constraints = []
|
||||
for line in relevant_lines:
|
||||
if (lcargs := symbols_list_to_lcargs(line, alloc, constants)) is None:
|
||||
return None
|
||||
constraints.append(Constraint(line, lcargs))
|
||||
return constraints
|
||||
|
||||
class Contract:
|
||||
|
||||
def __init__(self, constants, alloc, ops, constraints):
|
||||
self.constants = constants
|
||||
self.alloc = alloc
|
||||
self.ops = ops
|
||||
self.constraints = constraints
|
||||
|
||||
def __repr__(self):
|
||||
repr_str = ""
|
||||
|
||||
repr_str += "Constants:\n"
|
||||
for symbol, value in self.constants.items():
|
||||
repr_str += " // %s\n" % symbol
|
||||
repr_str += " %s: %s\n" % value
|
||||
|
||||
repr_str += "Alloc table:\n"
|
||||
for symbol, variable in self.alloc.items():
|
||||
repr_str += " // %s\n" % symbol
|
||||
repr_str += " %s %s\n" % (variable.type, variable.index)
|
||||
|
||||
repr_str += "Operations:\n"
|
||||
for op in self.ops:
|
||||
repr_str += " // %s\n" % op.line
|
||||
repr_str += " %s %s\n" % (op.command, op.args)
|
||||
|
||||
repr_str += "Constraints:\n"
|
||||
for constraint in self.constraints:
|
||||
if constraint.args:
|
||||
repr_str += " // %s\n" % constraint.args_comment()
|
||||
repr_str += " %s %s\n" % (constraint.command, constraint.args)
|
||||
|
||||
repr_str += "Stats:\n"
|
||||
repr_str += " Constants: %s\n" % len(self.constants)
|
||||
repr_str += " Alloc: %s\n" % len(self.alloc)
|
||||
repr_str += " Operations: %s\n" % len(self.ops)
|
||||
repr_str += " Constraint Instructions: %s\n" % len(self.constraints)
|
||||
|
||||
return repr_str
|
||||
|
||||
def compile(contract, constants):
|
||||
# Allocation table
|
||||
# symbol: Private/Public, is_param, index
|
||||
if (alloc := generate_alloc_table(contract)) is None:
|
||||
return None
|
||||
# Operations lines list
|
||||
if (ops := generate_ops_table(contract, alloc, constants)) is None:
|
||||
return None
|
||||
# Constraint commands
|
||||
if (constraints := generate_constraints_table(
|
||||
contract, alloc, constants)) is None:
|
||||
return None
|
||||
return Contract(constants, alloc, ops, constraints)
|
||||
|
||||
def parse_constants(contents):
|
||||
relevant_lines = [line for line in contents if line.command() == "constant"]
|
||||
constants = {}
|
||||
for line in relevant_lines:
|
||||
assert line.command() == "constant"
|
||||
if len(line.args()) != 2:
|
||||
eprint("error: wrong number of args for constant")
|
||||
eprint(line)
|
||||
return None
|
||||
symbol, value = line.args()
|
||||
|
||||
try:
|
||||
int(value, 16)
|
||||
except ValueError:
|
||||
eprint("error: invalid constant value for '%s'" % symbol)
|
||||
eprint(line)
|
||||
return None
|
||||
|
||||
if len(value) != 32*2 + 2 or value[:2] != "0x":
|
||||
eprint("error: invalid hex value for constant")
|
||||
eprint(line)
|
||||
return None
|
||||
|
||||
# Remove 0x prefix
|
||||
value = value[2:]
|
||||
|
||||
constants[symbol] = (len(constants), value)
|
||||
return constants
|
||||
|
||||
def process(contents):
|
||||
# Remove left whitespace
|
||||
contents = clean(contents)
|
||||
# Parse all constants
|
||||
if (constants := parse_constants(contents)) is None:
|
||||
return None
|
||||
# Divide into contract sections
|
||||
if (pre_contracts := divide_sections(contents)) is None:
|
||||
return None
|
||||
# Process each contract
|
||||
contracts = {}
|
||||
for contract_name, pre_contract in pre_contracts.items():
|
||||
if (contract := compile(pre_contract, constants)) is None:
|
||||
return None
|
||||
contracts[contract_name] = contract
|
||||
return contracts
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("filename", help="VM PISM file: proofs/vm.pism")
|
||||
parser.add_argument("--output", type=argparse.FileType('wb', 0),
|
||||
default=sys.stdout.buffer, help="Output file")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--display', action='store_true',
|
||||
help="show the compiled code in human readable format")
|
||||
group.add_argument('--rust', action='store_true',
|
||||
help="output compiled code to rust for testing")
|
||||
group.add_argument('--supervisor', action='store_true',
|
||||
help="output compiled code to zkvm supervisor")
|
||||
args = parser.parse_args()
|
||||
|
||||
src_filename = args.filename
|
||||
contents = open(src_filename).read()
|
||||
if (contracts := process(contents)) is None:
|
||||
return -2
|
||||
|
||||
def default_display():
|
||||
for contract_name, contract in contracts.items():
|
||||
print("Contract:", contract_name)
|
||||
print(contract)
|
||||
|
||||
if args.display:
|
||||
default_display()
|
||||
elif args.rust:
|
||||
import compile_export_rust
|
||||
for contract_name, contract in contracts.items():
|
||||
compile_export_rust.display(contract)
|
||||
elif args.supervisor:
|
||||
import compile_export_supervisor
|
||||
for contract_name, contract in contracts.items():
|
||||
compile_export_supervisor.export(args.output, contract_name,
|
||||
contract)
|
||||
else:
|
||||
default_display()
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
from compile import VariableType, VariableRefType
|
||||
|
||||
def to_initial_caps(snake_str):
|
||||
components = snake_str.split("_")
|
||||
return "".join(x.title() for x in components)
|
||||
|
||||
def display(contract):
|
||||
indent = " " * 4
|
||||
|
||||
print(r"""use super::vm::{ZkVirtualMachine, CryptoOperation, AllocType, ConstraintInstruction, VariableIndex, VariableRef};
|
||||
use bls12_381::Scalar;
|
||||
|
||||
pub fn load_params(params: Vec<Scalar>) -> Vec<(VariableIndex, Scalar)> {""")
|
||||
params = [(symbol, var) for symbol, var in contract.alloc.items() if var.is_param]
|
||||
print("%sassert_eq!(params.len(), %s);" % (indent, len(params)))
|
||||
print("%slet mut result = vec![(0, Scalar::zero()); %s];" % (
|
||||
indent, len(params)))
|
||||
for i, (symbol, variable) in enumerate(params):
|
||||
assert variable.is_param
|
||||
print("%s// %s" % (indent, symbol))
|
||||
print("%sresult[%s] = (%s, params[%s]);" % (
|
||||
indent, i, variable.index, i))
|
||||
print("%sresult" % indent)
|
||||
print("}\n")
|
||||
|
||||
print(r"""pub fn load_zkvm() -> ZkVirtualMachine {
|
||||
ZkVirtualMachine {
|
||||
constants: vec![""")
|
||||
|
||||
constants = list(contract.constants.items())
|
||||
constants.sort(key=lambda obj: obj[1][0])
|
||||
constants = [(obj[0], obj[1][1]) for obj in constants]
|
||||
for symbol, value in constants:
|
||||
print("%s// %s" % (indent * 3, symbol))
|
||||
assert len(value) == 32*2
|
||||
chunk_str = lambda line, n: \
|
||||
[line[i:i + n] for i in range(0, len(line), n)]
|
||||
chunks = chunk_str(value, 2)
|
||||
# Reverse the endianness
|
||||
# We allow literal numbers but rust wants little endian
|
||||
chunks = chunks[::-1]
|
||||
print("%sScalar::from_bytes(&[" % (indent * 3))
|
||||
for i in range(0, 32, 4):
|
||||
print("%s0x%s, 0x%s, 0x%s, 0x%s," % (indent * 4,
|
||||
chunks[i], chunks[i + 1], chunks[i + 2], chunks[i + 3]))
|
||||
print("%s]).unwrap()," % (indent * 3))
|
||||
|
||||
print("%s]," % (indent * 2))
|
||||
print("%salloc: vec![" % (indent * 2))
|
||||
|
||||
for symbol, variable in contract.alloc.items():
|
||||
print("%s// %s" % (indent * 3, symbol))
|
||||
|
||||
if variable.type.name == VariableType.PRIVATE.name:
|
||||
typestring = "Private"
|
||||
elif variable.type.name == VariableType.PUBLIC.name:
|
||||
typestring = "Public"
|
||||
else:
|
||||
assert False
|
||||
|
||||
print("%s(AllocType::%s, %s)," % (indent * 3, typestring,
|
||||
variable.index))
|
||||
|
||||
print("%s]," % (indent * 2))
|
||||
print("%sops: vec![" % (indent * 2))
|
||||
|
||||
def var_ref_str(var_ref):
|
||||
if var_ref.type.name == VariableRefType.AUX.name:
|
||||
return "VariableRef::Aux(%s)" % var_ref.index
|
||||
elif var_ref.type.name == VariableRefType.LOCAL.name:
|
||||
return "VariableRef::Local(%s)" % var_ref.index
|
||||
else:
|
||||
assert False
|
||||
|
||||
for op in contract.ops:
|
||||
print("%s// %s" % (indent * 3, op.line))
|
||||
args_part = ""
|
||||
if op.command == "load":
|
||||
assert len(op.args) == 2
|
||||
args_part = "(%s, %s)" % (var_ref_str(op.args[0]), op.args[1].index)
|
||||
elif op.command == "debug":
|
||||
assert len(op.args) == 1
|
||||
args_part = '(String::from("%s"), %s)' % (
|
||||
op.line, var_ref_str(op.args[0]))
|
||||
elif op.args:
|
||||
args_part = ", ".join(var_ref_str(var_ref) for var_ref in op.args)
|
||||
args_part = "(%s)" % args_part
|
||||
print("%sCryptoOperation::%s%s," % (
|
||||
indent * 3,
|
||||
to_initial_caps(op.command),
|
||||
args_part
|
||||
))
|
||||
|
||||
print("%s]," % (indent * 2))
|
||||
print("%sconstraints: vec![" % (indent * 2))
|
||||
|
||||
for constraint in contract.constraints:
|
||||
args_part = ""
|
||||
if constraint.args:
|
||||
print("%s// %s" % (indent *3, constraint.args_comment()))
|
||||
args = constraint.args[:]
|
||||
if (constraint.command == "lc0_add_coeff" or
|
||||
constraint.command == "lc1_add_coeff" or
|
||||
constraint.command == "lc2_add_coeff" or
|
||||
constraint.command == "lc0_add_one_coeff" or
|
||||
constraint.command == "lc1_add_one_coeff" or
|
||||
constraint.command == "lc2_add_one_coeff"):
|
||||
args[0] = args[0][0]
|
||||
args_part = ", ".join(str(index) for index in args)
|
||||
args_part = "(%s)" % args_part
|
||||
print("%sConstraintInstruction::%s%s," % (
|
||||
indent * 3,
|
||||
to_initial_caps(constraint.command),
|
||||
args_part
|
||||
))
|
||||
print(r""" ],
|
||||
aux: vec![],
|
||||
params: None,
|
||||
verifying_key: None,
|
||||
}
|
||||
}""")
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
import struct
|
||||
from compile import VariableType, VariableRefType
|
||||
|
||||
class Operation:
|
||||
|
||||
def __init__(self, ident, args):
|
||||
self.ident = ident
|
||||
self.args = args
|
||||
|
||||
class ArgVarRef:
|
||||
|
||||
def __init__(self, type, index):
|
||||
self.type = type
|
||||
self.index = index
|
||||
|
||||
def bytes(self):
|
||||
return struct.pack("<BI", self.type, self.index)
|
||||
|
||||
class ArgVarIndex:
|
||||
|
||||
def __init__(self, _, index):
|
||||
self.index = index
|
||||
|
||||
def bytes(self):
|
||||
return struct.pack("<I", self.index)
|
||||
|
||||
class ArgString:
|
||||
|
||||
def __init__(self, description, index):
|
||||
self.description = description
|
||||
self.index = index
|
||||
|
||||
ops_table = {
|
||||
"set": Operation(0, [ArgVarRef, ArgVarRef]),
|
||||
"mul": Operation(1, [ArgVarRef, ArgVarRef]),
|
||||
"add": Operation(2, [ArgVarRef, ArgVarRef]),
|
||||
"sub": Operation(3, [ArgVarRef, ArgVarRef]),
|
||||
"divide": Operation(4, [ArgVarRef, ArgVarRef]),
|
||||
"double": Operation(5, [ArgVarRef]),
|
||||
"square": Operation(6, [ArgVarRef]),
|
||||
"invert": Operation(7, [ArgVarRef]),
|
||||
"unpack_bits": Operation(8, [ArgVarRef, ArgVarRef, ArgVarRef]),
|
||||
"local": Operation(9, []),
|
||||
"load": Operation(10, [ArgVarRef, ArgVarIndex]),
|
||||
"debug": Operation(11, [ArgString, ArgVarRef]),
|
||||
"dump_alloc": Operation(12, []),
|
||||
"dump_local": Operation(13, []),
|
||||
}
|
||||
|
||||
constraint_ident_map = {
|
||||
"lc0_add": 0,
|
||||
"lc1_add": 1,
|
||||
"lc2_add": 2,
|
||||
"lc0_sub": 3,
|
||||
"lc1_sub": 4,
|
||||
"lc2_sub": 5,
|
||||
"lc0_add_one": 6,
|
||||
"lc1_add_one": 7,
|
||||
"lc2_add_one": 8,
|
||||
"lc0_sub_one": 9,
|
||||
"lc1_sub_one": 10,
|
||||
"lc2_sub_one": 11,
|
||||
"lc0_add_coeff": 12,
|
||||
"lc1_add_coeff": 13,
|
||||
"lc2_add_coeff": 14,
|
||||
"lc0_add_constant": 15,
|
||||
"lc1_add_constant": 16,
|
||||
"lc2_add_constant": 17,
|
||||
"enforce": 18,
|
||||
"lc_coeff_reset": 19,
|
||||
"lc_coeff_double": 20,
|
||||
}
|
||||
|
||||
def varuint(value):
|
||||
if value <= 0xfc:
|
||||
return struct.pack("<B", value)
|
||||
elif value <= 0xffff:
|
||||
return struct.pack("<BH", 0xfd, value)
|
||||
elif value <= 0xffffffff:
|
||||
return struct.pack("<BI", 0xfe, value)
|
||||
else:
|
||||
return struct.pack("<BQ", 0xff, value)
|
||||
|
||||
def export(output, contract_name, contract):
|
||||
output.write(varuint(len(contract_name)))
|
||||
output.write(contract_name.encode())
|
||||
|
||||
constants = list(contract.constants.items())
|
||||
constants.sort(key=lambda obj: obj[1][0])
|
||||
constants = [(obj[0], obj[1][1]) for obj in constants]
|
||||
|
||||
# Constants
|
||||
output.write(varuint(len(constants)))
|
||||
for symbol, value in constants:
|
||||
print("Constant '%s' = %s" % (symbol, value))
|
||||
# Bellman uses little endian for Scalars from_bytes function
|
||||
const_bytes = bytearray.fromhex(value)[::-1]
|
||||
assert len(const_bytes) == 32
|
||||
output.write(const_bytes)
|
||||
|
||||
# Alloc
|
||||
output.write(varuint(len(contract.alloc)))
|
||||
for symbol, variable in contract.alloc.items():
|
||||
print("Alloc '%s' = (%s, %s)" % (symbol,
|
||||
variable.type.name, variable.index))
|
||||
if variable.type.name == VariableType.PRIVATE.name:
|
||||
typeval = 0
|
||||
elif variable.type.name == VariableType.PUBLIC.name:
|
||||
typeval = 1
|
||||
else:
|
||||
assert False
|
||||
alloc_bytes = struct.pack("<BI", typeval, variable.index)
|
||||
assert len(alloc_bytes) == 5
|
||||
output.write(alloc_bytes)
|
||||
|
||||
# Ops
|
||||
output.write(varuint(len(contract.ops)))
|
||||
for op in contract.ops:
|
||||
op_form = ops_table[op.command]
|
||||
output.write(struct.pack("B", op_form.ident))
|
||||
|
||||
if op.command == "debug":
|
||||
# Special case
|
||||
assert len(op.args) == 1
|
||||
line_str = str(op.line).encode()
|
||||
output.write(varuint(len(line_str)))
|
||||
output.write(line_str)
|
||||
|
||||
op_arg = op.args[0]
|
||||
if op_arg.type.name == VariableRefType.AUX.name:
|
||||
arg_type = 0
|
||||
elif op_arg.type.name == VariableRefType.LOCAL.name:
|
||||
arg_type = 1
|
||||
arg = ArgVarRef(arg_type, op_arg.index)
|
||||
output.write(arg.bytes())
|
||||
continue
|
||||
|
||||
assert len(op_form.args) == len(op.args)
|
||||
for arg_form, op_arg in zip(op_form.args, op.args):
|
||||
if op_arg.type.name == VariableRefType.AUX.name:
|
||||
arg_type = 0
|
||||
elif op_arg.type.name == VariableRefType.LOCAL.name:
|
||||
arg_type = 1
|
||||
arg = arg_form(arg_type, op_arg.index)
|
||||
output.write(arg.bytes())
|
||||
print("#", op.line)
|
||||
print("Operation", op.command,
|
||||
[(arg.type.name, arg.index) for arg in op.args])
|
||||
|
||||
# Constraints
|
||||
output.write(varuint(len(contract.constraints)))
|
||||
for constraint in contract.constraints:
|
||||
args = constraint.args[:]
|
||||
if (constraint.command == "lc0_add_coeff" or
|
||||
constraint.command == "lc1_add_coeff" or
|
||||
constraint.command == "lc2_add_coeff" or
|
||||
constraint.command == "lc0_add_constant" or
|
||||
constraint.command == "lc1_add_constant" or
|
||||
constraint.command == "lc2_add_constant"):
|
||||
args[0] = args[0][0]
|
||||
print("#", constraint.line)
|
||||
print("Constraint", constraint.command, args if args else "")
|
||||
enum_ident = constraint_ident_map[constraint.command]
|
||||
output.write(struct.pack("B", enum_ident))
|
||||
for arg in args:
|
||||
output.write(struct.pack("<I", arg))
|
||||
|
||||
# Params Map
|
||||
param_alloc = [(symbol, variable) for (symbol, variable)
|
||||
in contract.alloc.items() if variable.is_param]
|
||||
output.write(varuint(len(param_alloc)))
|
||||
for symbol, variable in param_alloc:
|
||||
assert variable.is_param
|
||||
print("Parameter '%s' = %s" % (symbol, variable.index))
|
||||
symbol = symbol.encode()
|
||||
output.write(varuint(len(symbol)))
|
||||
output.write(symbol)
|
||||
output.write(struct.pack("<I", variable.index))
|
||||
|
||||
# Public Map
|
||||
public_alloc = [(symbol, variable) for (symbol, variable)
|
||||
in contract.alloc.items()
|
||||
if variable.type.name == VariableType.PUBLIC.name]
|
||||
output.write(varuint(len(public_alloc)))
|
||||
for symbol, variable in public_alloc:
|
||||
assert not variable.is_param
|
||||
assert variable.type.name == VariableType.PUBLIC.name
|
||||
print("Public '%s' = %s" % (symbol, variable.index))
|
||||
symbol = symbol.encode()
|
||||
output.write(varuint(len(symbol)))
|
||||
output.write(symbol)
|
||||
output.write(struct.pack("<I", variable.index))
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
if exists('b:current_syntax')
|
||||
finish
|
||||
endif
|
||||
|
||||
syn keyword drkKeyword assert enforce for in def return const as let emit contract private proof
|
||||
syn keyword drkAttr mut
|
||||
syn keyword drkType BinaryNumber Point Fr SubgroupPoint EdwardsPoint Scalar EncryptedNum list Bool U64 Num Binary
|
||||
syn match drkFunction "\zs[a-zA-Z0-9_]*\ze("
|
||||
syn match drkComment "#.*$"
|
||||
syn match drkNumber '\d\+'
|
||||
syn match drkConst '[A-Z_]\{2,}[A-Z0-9_]*'
|
||||
|
||||
hi def link drkKeyword Statement
|
||||
hi def link drkAttr StorageClass
|
||||
hi def link drkType Type
|
||||
hi def link drkFunction Function
|
||||
hi def link drkComment Comment
|
||||
hi def link drkNumber Constant
|
||||
hi def link drkConst Constant
|
||||
|
||||
let b:current_syntax = "drk"
|
||||
@@ -1,40 +0,0 @@
|
||||
from finite_fields import finitefield
|
||||
|
||||
def add(x_1, y_1, x_2, y_2):
|
||||
if (x_1, y_1) == (x_2, y_2):
|
||||
if y_1 == 0:
|
||||
return None
|
||||
|
||||
# slope of the tangent line
|
||||
m = (3 * x_1 * x_1 + a) / (2 * y_1)
|
||||
return None
|
||||
else:
|
||||
if x_1 == x_2:
|
||||
return None
|
||||
|
||||
# slope of the secant line
|
||||
m = (y_2 - y_1) / (x_2 - x_1)
|
||||
|
||||
x_3 = m*m - x_1 - x_2
|
||||
y_3 = m*(x_1 - x_3) - y_1
|
||||
|
||||
return (x_3, y_3)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Vesta
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
fq = finitefield.IntegersModP(q)
|
||||
|
||||
a, b = fq(0x00), fq(0x05)
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
|
||||
C = (fq(0x1ca18c7c3fcb110f9e92c694ce552238f95e9f9b911599cedaff6018cfc5ed52), fq(0x3ad6133a791e41f3e062d370b40e97e77d20effc00b7ee88c4bb097d245cb438))
|
||||
D = (fq(0x3e544e611bb895166afe1a46c6e551c47968daf962d824f79f795cb53585b098), fq(0x2fd03c4da47baf2dfd251e85d18864d4885ddd0e8df648550565b850b79349e3))
|
||||
C_plus_D = (fq(0x06f822cbde350215558c46aac9e60eee31afd942ca6da568845ca4f8fe911e17), fq(0x3e294e73970abc197dfff1a14e74cb20c11b81422d9f920c7b0b0c63affdf67b))
|
||||
|
||||
result = add(C[0], C[1], D[0], D[1])
|
||||
print(result)
|
||||
print(list("%x" % x.n for x in result))
|
||||
assert result[0] == C_plus_D[0]
|
||||
assert result[1] == C_plus_D[1]
|
||||
@@ -1 +0,0 @@
|
||||
../finite_fields/
|
||||
@@ -1,4 +0,0 @@
|
||||
finite-fields
|
||||
=============
|
||||
|
||||
Python code and tests for the post ["Programming with Finite Fields"](http://jeremykun.com/2014/03/13/programming-with-finite-fields/)
|
||||
@@ -1,45 +0,0 @@
|
||||
from test import test
|
||||
from euclidean import *
|
||||
|
||||
test(1, gcd(7, 9))
|
||||
test(2, gcd(8, 18))
|
||||
test(-12, gcd(-12, 24))
|
||||
test(12, gcd(12, -24)) # gcd is only unique up to multiplication by a unit, and so sometimes we'll get negatives.
|
||||
test(38, gcd(4864, 3458))
|
||||
|
||||
test((32, -45, 38), extendedEuclideanAlgorithm(4864, 3458))
|
||||
test((-45, 32, 38), extendedEuclideanAlgorithm(3458, 4864))
|
||||
|
||||
from modp import *
|
||||
|
||||
Mod2 = IntegersModP(2)
|
||||
test(Mod2(1), gcd(Mod2(1), Mod2(0)))
|
||||
test(Mod2(1), gcd(Mod2(1), Mod2(1)))
|
||||
test(Mod2(0), gcd(Mod2(2), Mod2(2)))
|
||||
|
||||
Mod7 = IntegersModP(7)
|
||||
test(Mod7(6), gcd(Mod7(6), Mod7(14)))
|
||||
test(Mod7(2), gcd(Mod7(6), Mod7(9)))
|
||||
|
||||
ModHuge = IntegersModP(9923)
|
||||
test(ModHuge(38), gcd(ModHuge(4864), ModHuge(3458)))
|
||||
test((ModHuge(32), ModHuge(-45), ModHuge(38)),
|
||||
extendedEuclideanAlgorithm(ModHuge(4864), ModHuge(3458)))
|
||||
|
||||
from polynomial import *
|
||||
|
||||
p = polynomialsOver(Mod7).factory
|
||||
test(p([-1, 1]), gcd(p([-1,0,1]), p([-1,0,0,1])))
|
||||
f = p([-1,0,1])
|
||||
g = p([-1,0,0,1])
|
||||
test((p([0,-1]), p([1]), p([-1, 1])), extendedEuclideanAlgorithm(f, g))
|
||||
test(p([-1,1]), f * p([0,-1]) + g * p([1]))
|
||||
|
||||
p = polynomialsOver(Mod2).factory
|
||||
f = p([1,0,0,0,1,1,1,0,1,1,1]) # x^10 + x^9 + x^8 + x^6 + x^5 + x^4 + 1
|
||||
g = p([1,0,1,1,0,1,1,0,0,1]) # x^9 + x^6 + x^5 + x^3 + x^1 + 1
|
||||
theGcd = p([1,1,0,1]) # x^3 + x + 1
|
||||
x = p([0,0,0,0,1]) # x^4
|
||||
y = p([1,1,1,1,1,1]) # x^5 + x^4 + x^3 + x^2 + x + 1
|
||||
|
||||
test((x, y, theGcd), extendedEuclideanAlgorithm(f, g))
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
# a general Euclidean algorithm for any number type with
|
||||
# a divmod and a valuation abs() whose minimum value is zero
|
||||
def gcd(a, b):
|
||||
if abs(a) < abs(b):
|
||||
return gcd(b, a)
|
||||
|
||||
while abs(b) > 0:
|
||||
_,r = divmod(a,b)
|
||||
a,b = b,r
|
||||
|
||||
return a
|
||||
|
||||
|
||||
# extendedEuclideanAlgorithm: int, int -> int, int, int
|
||||
# input (a,b) and output three numbers x,y,d such that ax + by = d = gcd(a,b).
|
||||
# Works for any number type with a divmod and a valuation abs()
|
||||
# whose minimum value is zero
|
||||
def extendedEuclideanAlgorithm(a, b):
|
||||
if abs(b) > abs(a):
|
||||
(x,y,d) = extendedEuclideanAlgorithm(b, a)
|
||||
return (y,x,d)
|
||||
|
||||
if abs(b) == 0:
|
||||
return (1, 0, a)
|
||||
|
||||
x1, x2, y1, y2 = 0, 1, 1, 0
|
||||
while abs(b) > 0:
|
||||
q, r = divmod(a,b)
|
||||
x = x2 - q*x1
|
||||
y = y2 - q*y1
|
||||
a, b, x2, x1, y2, y1 = b, r, x1, x, y1, y
|
||||
|
||||
return (x2, y2, a)
|
||||
@@ -1,28 +0,0 @@
|
||||
from test import test
|
||||
from finitefield import *
|
||||
from polynomial import *
|
||||
from modp import *
|
||||
|
||||
def p(L, q):
|
||||
f = IntegersModP(q)
|
||||
Polynomial = polynomialsOver(f).factory
|
||||
return Polynomial(L)
|
||||
|
||||
test(True, isIrreducible(p([0,1], 2), 2))
|
||||
test(False, isIrreducible(p([1,0,1], 2), 2))
|
||||
test(True, isIrreducible(p([1,0,1], 3), 3))
|
||||
|
||||
test(False, isIrreducible(p([1,0,0,1], 5), 5))
|
||||
test(False, isIrreducible(p([1,0,0,1], 7), 7))
|
||||
test(False, isIrreducible(p([1,0,0,1], 11), 11))
|
||||
|
||||
|
||||
test(True, isIrreducible(p([-2, 0, 1], 13), 13))
|
||||
|
||||
|
||||
Z5 = IntegersModP(5)
|
||||
Poly = polynomialsOver(Z5).factory
|
||||
f = Poly([3,0,1])
|
||||
F25 = FiniteField(5, 2, polynomialModulus=f)
|
||||
x = F25([2,1])
|
||||
test(Poly([1,2]), x.inverse())
|
||||
@@ -1,128 +0,0 @@
|
||||
import random
|
||||
from .polynomial import polynomialsOver
|
||||
from .modp import *
|
||||
|
||||
|
||||
|
||||
# isIrreducible: Polynomial, int -> bool
|
||||
# determine if the given monic polynomial with coefficients in Z/p is
|
||||
# irreducible over Z/p where p is the given integer
|
||||
# Algorithm 4.69 in the Handbook of Applied Cryptography
|
||||
def isIrreducible(polynomial, p):
|
||||
ZmodP = IntegersModP(p)
|
||||
if polynomial.field is not ZmodP:
|
||||
raise TypeError("Given a polynomial that's not over %s, but instead %r" %
|
||||
(ZmodP.__name__, polynomial.field.__name__))
|
||||
|
||||
poly = polynomialsOver(ZmodP).factory
|
||||
x = poly([0,1])
|
||||
powerTerm = x
|
||||
isUnit = lambda p: p.degree() == 0
|
||||
|
||||
for _ in range(int(polynomial.degree() / 2)):
|
||||
powerTerm = powerTerm.powmod(p, polynomial)
|
||||
gcdOverZmodp = gcd(polynomial, powerTerm - x)
|
||||
if not isUnit(gcdOverZmodp):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# generateIrreduciblePolynomial: int, int -> Polynomial
|
||||
# generate a random irreducible polynomial of a given degree over Z/p, where p
|
||||
# is given by the integer 'modulus'. This algorithm is expected to terminate
|
||||
# after 'degree' many irreducilibity tests. By Chernoff bounds the probability
|
||||
# it deviates from this by very much is exponentially small.
|
||||
def generateIrreduciblePolynomial(modulus, degree):
|
||||
Zp = IntegersModP(modulus)
|
||||
Polynomial = polynomialsOver(Zp)
|
||||
|
||||
while True:
|
||||
coefficients = [Zp(random.randint(0, modulus-1)) for _ in range(degree)]
|
||||
randomMonicPolynomial = Polynomial(coefficients + [Zp(1)])
|
||||
print(randomMonicPolynomial)
|
||||
|
||||
if isIrreducible(randomMonicPolynomial, modulus):
|
||||
return randomMonicPolynomial
|
||||
|
||||
|
||||
# create a type constructor for the finite field of order p^m for p prime, m >= 1
|
||||
@memoize
|
||||
def FiniteField(p, m, polynomialModulus=None):
|
||||
Zp = IntegersModP(p)
|
||||
if m == 1:
|
||||
return Zp
|
||||
|
||||
Polynomial = polynomialsOver(Zp)
|
||||
if polynomialModulus is None:
|
||||
polynomialModulus = generateIrreduciblePolynomial(modulus=p, degree=m)
|
||||
|
||||
class Fq(FieldElement):
|
||||
fieldSize = int(p ** m)
|
||||
primeSubfield = Zp
|
||||
idealGenerator = polynomialModulus
|
||||
operatorPrecedence = 3
|
||||
|
||||
def __init__(self, poly):
|
||||
if type(poly) is Fq:
|
||||
self.poly = poly.poly
|
||||
elif type(poly) is int or type(poly) is Zp:
|
||||
self.poly = Polynomial([Zp(poly)])
|
||||
elif isinstance(poly, Polynomial):
|
||||
self.poly = poly % polynomialModulus
|
||||
else:
|
||||
self.poly = Polynomial([Zp(x) for x in poly]) % polynomialModulus
|
||||
|
||||
self.field = Fq
|
||||
|
||||
@typecheck
|
||||
def __add__(self, other): return Fq(self.poly + other.poly)
|
||||
@typecheck
|
||||
def __sub__(self, other): return Fq(self.poly - other.poly)
|
||||
@typecheck
|
||||
def __mul__(self, other): return Fq(self.poly * other.poly)
|
||||
@typecheck
|
||||
def __eq__(self, other): return isinstance(other, Fq) and self.poly == other.poly
|
||||
@typecheck
|
||||
def __ne__(self, other): return not self == other
|
||||
|
||||
def __pow__(self, n):
|
||||
if n==0: return Fq([1])
|
||||
if n==1: return self
|
||||
if n%2==0:
|
||||
sqrut = self**(n//2)
|
||||
return sqrut*sqrut
|
||||
if n%2==1: return (self**(n-1))*self
|
||||
|
||||
#def __pow__(self, n): return Fq(pow(self.poly, n))
|
||||
def __neg__(self): return Fq(-self.poly)
|
||||
def __abs__(self): return abs(self.poly)
|
||||
def __repr__(self): return repr(self.poly) + ' \u2208 ' + self.__class__.__name__
|
||||
|
||||
@typecheck
|
||||
def __divmod__(self, divisor):
|
||||
q,r = divmod(self.poly, divisor.poly)
|
||||
return (Fq(q), Fq(r))
|
||||
|
||||
|
||||
def inverse(self):
|
||||
if self == Fq(0):
|
||||
raise ZeroDivisionError
|
||||
|
||||
x,y,d = extendedEuclideanAlgorithm(self.poly, self.idealGenerator)
|
||||
if d.degree() != 0:
|
||||
raise Exception('Somehow, this element has no inverse! Maybe intialized with a non-prime?')
|
||||
|
||||
return Fq(x) * Fq(d.coefficients[0].inverse())
|
||||
|
||||
|
||||
Fq.__name__ = 'F_{%d^%d}' % (p,m)
|
||||
return Fq
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
F23 = FiniteField(2,3)
|
||||
x = F23([1,1])
|
||||
|
||||
F35 = FiniteField(3,5)
|
||||
y = F35([1,1,2])
|
||||
@@ -1,12 +0,0 @@
|
||||
from modp import *
|
||||
from test import test
|
||||
|
||||
mod7 = IntegersModP(7)
|
||||
|
||||
test(mod7(5), mod7(5)) # Sanity check
|
||||
test(mod7(5), 1 / mod7(3))
|
||||
test(mod7(1), mod7(3) * mod7(5))
|
||||
test(mod7(3), mod7(3) * 1)
|
||||
test(mod7(2), mod7(5) + mod7(4))
|
||||
|
||||
test(True, mod7(0) == mod7(3) + mod7(4))
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
from .euclidean import *
|
||||
from .numbertype import *
|
||||
|
||||
# so all IntegersModP are instances of the same base class
|
||||
class _Modular(FieldElement):
|
||||
pass
|
||||
|
||||
|
||||
@memoize
|
||||
def IntegersModP(p):
|
||||
# assume p is prime
|
||||
|
||||
class IntegerModP(_Modular):
|
||||
def __init__(self, n):
|
||||
try:
|
||||
self.n = int(n) % IntegerModP.p
|
||||
except:
|
||||
raise TypeError("Can't cast type %s to %s in __init__" %
|
||||
(type(n).__name__, type(self).__name__))
|
||||
|
||||
self.field = IntegerModP
|
||||
|
||||
@typecheck
|
||||
def __add__(self, other):
|
||||
return IntegerModP(self.n + other.n)
|
||||
|
||||
@typecheck
|
||||
def __sub__(self, other):
|
||||
return IntegerModP(self.n - other.n)
|
||||
|
||||
@typecheck
|
||||
def __mul__(self, other):
|
||||
return IntegerModP(self.n * other.n)
|
||||
|
||||
def __neg__(self):
|
||||
return IntegerModP(-self.n)
|
||||
|
||||
@typecheck
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, IntegerModP) and self.n == other.n
|
||||
|
||||
@typecheck
|
||||
def __ne__(self, other):
|
||||
return isinstance(other, IntegerModP) is False or self.n != other.n
|
||||
|
||||
@typecheck
|
||||
def __divmod__(self, divisor):
|
||||
q,r = divmod(self.n, divisor.n)
|
||||
return (IntegerModP(q), IntegerModP(r))
|
||||
|
||||
def inverse(self):
|
||||
# need to use the division algorithm *as integers* because we're
|
||||
# doing it on the modulus itself (which would otherwise be zero)
|
||||
x,y,d = extendedEuclideanAlgorithm(self.n, self.p)
|
||||
|
||||
if d != 1:
|
||||
raise Exception("Error: p is not prime in %s!" % (self.__name__))
|
||||
|
||||
return IntegerModP(x)
|
||||
|
||||
def __abs__(self):
|
||||
return abs(self.n)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.n)
|
||||
|
||||
def __repr__(self):
|
||||
return '%d (mod %d)' % (self.n, self.p)
|
||||
|
||||
def __int__(self):
|
||||
return self.n
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.n, self.p))
|
||||
|
||||
IntegerModP.p = p
|
||||
IntegerModP.__name__ = 'Z/%d' % (p)
|
||||
IntegerModP.englishName = 'IntegersMod%d' % (p)
|
||||
return IntegerModP
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mod7 = IntegersModP(7)
|
||||
@@ -1,97 +0,0 @@
|
||||
# memoize calls to the class constructors for fields
|
||||
# this helps typechecking by never creating two separate
|
||||
# instances of a number class.
|
||||
def memoize(f):
|
||||
cache = {}
|
||||
|
||||
def memoizedFunction(*args, **kwargs):
|
||||
argTuple = args + tuple(kwargs)
|
||||
if argTuple not in cache:
|
||||
cache[argTuple] = f(*args, **kwargs)
|
||||
return cache[argTuple]
|
||||
|
||||
memoizedFunction.cache = cache
|
||||
return memoizedFunction
|
||||
|
||||
|
||||
# type check a binary operation, and silently typecast 0 or 1
|
||||
def typecheck(f):
|
||||
def newF(self, other):
|
||||
if (hasattr(other.__class__, 'operatorPrecedence') and
|
||||
other.__class__.operatorPrecedence > self.__class__.operatorPrecedence):
|
||||
return NotImplemented
|
||||
|
||||
if type(self) is not type(other):
|
||||
try:
|
||||
other = self.__class__(other)
|
||||
except TypeError:
|
||||
message = 'Not able to typecast %s of type %s to type %s in function %s'
|
||||
raise TypeError(message % (other, type(other).__name__, type(self).__name__, f.__name__))
|
||||
except Exception as e:
|
||||
message = 'Type error on arguments %r, %r for functon %s. Reason:%s'
|
||||
raise TypeError(message % (self, other, f.__name__, type(other).__name__, type(self).__name__, e))
|
||||
|
||||
return f(self, other)
|
||||
|
||||
return newF
|
||||
|
||||
|
||||
|
||||
# require a subclass to implement +-* neg and to perform typechecks on all of
|
||||
# the binary operations finally, the __init__ must operate when given a single
|
||||
# argument, provided that argument is the int zero or one
|
||||
class DomainElement(object):
|
||||
operatorPrecedence = 1
|
||||
|
||||
# the 'r'-operators are only used when typecasting ints
|
||||
def __radd__(self, other): return self + other
|
||||
def __rsub__(self, other): return -self + other
|
||||
def __rmul__(self, other): return self * other
|
||||
|
||||
# square-and-multiply algorithm for fast exponentiation
|
||||
def __pow__(self, n):
|
||||
if type(n) is not int:
|
||||
raise TypeError
|
||||
|
||||
Q = self
|
||||
R = self if n & 1 else self.__class__(1)
|
||||
|
||||
i = 2
|
||||
while i <= n:
|
||||
Q = (Q * Q)
|
||||
|
||||
if n & i == i:
|
||||
R = (Q * R)
|
||||
|
||||
i = i << 1
|
||||
|
||||
return R
|
||||
|
||||
|
||||
# requires the additional % operator (i.e. a Euclidean Domain)
|
||||
def powmod(self, n, modulus):
|
||||
if type(n) is not int:
|
||||
raise TypeError
|
||||
|
||||
Q = self
|
||||
R = self if n & 1 else self.__class__(1)
|
||||
|
||||
i = 2
|
||||
while i <= n:
|
||||
Q = (Q * Q) % modulus
|
||||
|
||||
if n & i == i:
|
||||
R = (Q * R) % modulus
|
||||
|
||||
i = i << 1
|
||||
|
||||
return R
|
||||
|
||||
|
||||
|
||||
# additionally require inverse() on subclasses
|
||||
class FieldElement(DomainElement):
|
||||
def __truediv__(self, other): return self * other.inverse()
|
||||
def __rtruediv__(self, other): return self.inverse() * other
|
||||
def __div__(self, other): return self.__truediv__(other)
|
||||
def __rdiv__(self, other): return self.__rtruediv__(other)
|
||||
@@ -1,51 +0,0 @@
|
||||
from __future__ import division
|
||||
from test import test
|
||||
from fractions import Fraction
|
||||
from polynomial import *
|
||||
|
||||
from modp import *
|
||||
|
||||
Mod5 = IntegersModP(5)
|
||||
Mod11 = IntegersModP(11)
|
||||
|
||||
polysOverQ = polynomialsOver(Fraction).factory
|
||||
polysMod5 = polynomialsOver(Mod5).factory
|
||||
polysMod11 = polynomialsOver(Mod11).factory
|
||||
|
||||
for p in [polysOverQ, polysMod5, polysMod11]:
|
||||
# equality
|
||||
test(True, p([]) == p([]))
|
||||
test(True, p([1,2]) == p([1,2]))
|
||||
test(True, p([1,2,0]) == p([1,2,0,0]))
|
||||
|
||||
# addition
|
||||
test(p([1,2,3]), p([1,0,3]) + p([0,2]))
|
||||
test(p([1,2,3]), p([1,2,3]) + p([]))
|
||||
test(p([5,2,3]), p([4]) + p([1,2,3]))
|
||||
test(p([1,2]), p([1,2,3]) + p([0,0,-3]))
|
||||
|
||||
# subtraction
|
||||
test(p([1,-2,3]), p([1,0,3]) - p([0,2]))
|
||||
test(p([1,2,3]), p([1,2,3]) - p([]))
|
||||
test(p([-1,-2,-3]), p([]) - p([1,2,3]))
|
||||
|
||||
# multiplication
|
||||
test(p([1,2,1]), p([1,1]) * p([1,1]))
|
||||
test(p([2,5,5,3]), p([2,3]) * p([1,1,1]))
|
||||
test(p([0,7,49]), p([0,1,7]) * p([7]))
|
||||
|
||||
# division
|
||||
test(p([1,1,1,1,1,1]), p([-1,0,0,0,0,0,1]) / p([-1,1]))
|
||||
test(p([-1,1,-1,1,-1,1]), p([1,0,0,0,0,0,1]) / p([1,1]))
|
||||
test(p([]), p([]) / p([1,1]))
|
||||
test(p([1,1]), p([1,1]) / p([1]))
|
||||
test(p([1,1]), p([2,2]) / p([2]))
|
||||
|
||||
# modulus
|
||||
test(p([]), p([1,7,49]) % p([7]))
|
||||
test(p([-7]), p([-3,10,-5,3]) % p([1,3]))
|
||||
|
||||
|
||||
test(polysOverQ([Fraction(1,7), 1, 7]), polysOverQ([1,7,49]) / polysOverQ([7]))
|
||||
test(polysMod5([1 / Mod5(7), 1, 7]), polysMod5([1,7,49]) / polysMod5([7]))
|
||||
test(polysMod11([1 / Mod11(7), 1, 7]), polysMod11([1,7,49]) / polysMod11([7]))
|
||||
@@ -1,143 +0,0 @@
|
||||
try:
|
||||
from itertools import zip_longest
|
||||
except ImportError:
|
||||
from itertools import izip_longest as zip_longest
|
||||
import fractions
|
||||
|
||||
from .numbertype import *
|
||||
|
||||
# strip all copies of elt from the end of the list
|
||||
def strip(L, elt):
|
||||
if len(L) == 0: return L
|
||||
|
||||
i = len(L) - 1
|
||||
while i >= 0 and L[i] == elt:
|
||||
i -= 1
|
||||
|
||||
return L[:i+1]
|
||||
|
||||
|
||||
# create a polynomial with coefficients in a field; coefficients are in
|
||||
# increasing order of monomial degree so that, for example, [1,2,3]
|
||||
# corresponds to 1 + 2x + 3x^2
|
||||
@memoize
|
||||
def polynomialsOver(field=fractions.Fraction):
|
||||
|
||||
class Polynomial(DomainElement):
|
||||
operatorPrecedence = 2
|
||||
|
||||
@classmethod
|
||||
def factory(cls, L):
|
||||
return Polynomial([cls.field(x) for x in L])
|
||||
|
||||
def __init__(self, c):
|
||||
if type(c) is Polynomial:
|
||||
self.coefficients = c.coefficients
|
||||
elif isinstance(c, field):
|
||||
self.coefficients = [c]
|
||||
elif not hasattr(c, '__iter__') and not hasattr(c, 'iter'):
|
||||
self.coefficients = [field(c)]
|
||||
else:
|
||||
self.coefficients = c
|
||||
|
||||
self.coefficients = strip(self.coefficients, field(0))
|
||||
|
||||
|
||||
def isZero(self): return self.coefficients == []
|
||||
|
||||
def __repr__(self):
|
||||
if self.isZero():
|
||||
return '0'
|
||||
|
||||
return ' + '.join(['%s x^%d' % (a,i) if i > 0 else '%s'%a
|
||||
for i,a in enumerate(self.coefficients)])
|
||||
|
||||
|
||||
def __abs__(self): return len(self.coefficients) # the valuation only gives 0 to the zero polynomial, i.e. 1+degree
|
||||
def __len__(self): return len(self.coefficients)
|
||||
def __sub__(self, other): return self + (-other)
|
||||
def __iter__(self): return iter(self.coefficients)
|
||||
def __neg__(self): return Polynomial([-a for a in self])
|
||||
|
||||
def iter(self): return self.__iter__()
|
||||
def leadingCoefficient(self): return self.coefficients[-1]
|
||||
def degree(self): return abs(self) - 1
|
||||
|
||||
@typecheck
|
||||
def __eq__(self, other):
|
||||
return self.degree() == other.degree() and all([x==y for (x,y) in zip(self, other)])
|
||||
|
||||
@typecheck
|
||||
def __ne__(self, other):
|
||||
return self.degree() != other.degree() or any([x!=y for (x,y) in zip(self, other)])
|
||||
|
||||
@typecheck
|
||||
def __add__(self, other):
|
||||
newCoefficients = [sum(x) for x in zip_longest(self, other, fillvalue=self.field(0))]
|
||||
return Polynomial(newCoefficients)
|
||||
|
||||
|
||||
@typecheck
|
||||
def __mul__(self, other):
|
||||
if self.isZero() or other.isZero():
|
||||
return Zero()
|
||||
|
||||
newCoeffs = [self.field(0) for _ in range(len(self) + len(other) - 1)]
|
||||
|
||||
for i,a in enumerate(self):
|
||||
for j,b in enumerate(other):
|
||||
newCoeffs[i+j] += a*b
|
||||
|
||||
return Polynomial(newCoeffs)
|
||||
|
||||
|
||||
@typecheck
|
||||
def __divmod__(self, divisor):
|
||||
quotient, remainder = Zero(), self
|
||||
divisorDeg = divisor.degree()
|
||||
divisorLC = divisor.leadingCoefficient()
|
||||
|
||||
while remainder.degree() >= divisorDeg:
|
||||
monomialExponent = remainder.degree() - divisorDeg
|
||||
monomialZeros = [self.field(0) for _ in range(monomialExponent)]
|
||||
monomialDivisor = Polynomial(monomialZeros + [remainder.leadingCoefficient() / divisorLC])
|
||||
|
||||
quotient += monomialDivisor
|
||||
remainder -= monomialDivisor * divisor
|
||||
|
||||
return quotient, remainder
|
||||
|
||||
|
||||
@typecheck
|
||||
def __truediv__(self, divisor):
|
||||
if divisor.isZero():
|
||||
raise ZeroDivisionError
|
||||
return divmod(self, divisor)[0]
|
||||
|
||||
|
||||
@typecheck
|
||||
def __mod__(self, divisor):
|
||||
if divisor.isZero():
|
||||
raise ZeroDivisionError
|
||||
return divmod(self, divisor)[1]
|
||||
|
||||
def __call__(self, x):
|
||||
if type(x) is int:
|
||||
x = self.field(x)
|
||||
assert type(x) is self.field
|
||||
if self.isZero():
|
||||
return self.field(0)
|
||||
y = self.leadingCoefficient()
|
||||
for coeff in self.coefficients[-2::-1]:
|
||||
y = y * x + coeff
|
||||
return y
|
||||
|
||||
|
||||
def Zero():
|
||||
return Polynomial([])
|
||||
|
||||
|
||||
Polynomial.field = field
|
||||
Polynomial.__name__ = '(%s)[x]' % field.__name__
|
||||
Polynomial.englishName = 'Polynomials in one variable over %s' % field.__name__
|
||||
return Polynomial
|
||||
@@ -1,8 +0,0 @@
|
||||
def test(expected, actual):
|
||||
if expected != actual:
|
||||
import sys, traceback
|
||||
(filename, lineno, container, code) = traceback.extract_stack()[-2]
|
||||
print("Test: %r failed on line %d in file %r.\nExpected %r but got %r\n" %
|
||||
(code, lineno, filename, expected, actual))
|
||||
|
||||
sys.exit(1)
|
||||
@@ -1,11 +0,0 @@
|
||||
from modp import *
|
||||
from polynomial import *
|
||||
|
||||
|
||||
mod3 = IntegersModP(3)
|
||||
Polynomial = polynomialsOver(mod3)
|
||||
x = mod3(1)
|
||||
p = Polynomial([1,2])
|
||||
|
||||
x+p
|
||||
p+x
|
||||
@@ -1,88 +0,0 @@
|
||||
# Notes from paper:
|
||||
# "Efficient Zero-Knowledge Arguments for Arithmetic Circuits in the
|
||||
# Discrete Log Setting" by Bootle and others (EUROCRYPT 2016)
|
||||
|
||||
from finite_fields import finitefield
|
||||
import numpy as np
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
fp = finitefield.IntegersModP(p)
|
||||
|
||||
# Number of variables
|
||||
m = 16
|
||||
# Number of rows for multiplication statements
|
||||
n = 3
|
||||
|
||||
N = n * m
|
||||
|
||||
# Initialize zeroed table
|
||||
aux = np.full(m, fp(0))
|
||||
|
||||
# From the zk-explainer document, we will represent the function:
|
||||
#
|
||||
# def foo(w, a, b):
|
||||
# if w:
|
||||
# return a * b
|
||||
# else:
|
||||
# return a + b
|
||||
#
|
||||
# Which can be translated mathematically to the statements:
|
||||
#
|
||||
# ab = m
|
||||
# w(m - a - b) = v - a - b
|
||||
# w^2 = w
|
||||
#
|
||||
# Where m is an intermediate value.
|
||||
|
||||
var_one = 0
|
||||
aux[var_one] = fp(1)
|
||||
|
||||
var_a = 1
|
||||
var_b = 2
|
||||
var_w = 3
|
||||
|
||||
aux[var_a] = fp(110)
|
||||
aux[var_b] = fp(4)
|
||||
aux[var_w] = fp(1)
|
||||
|
||||
# Calculate intermediate advice values
|
||||
var_m = 4
|
||||
aux[var_m] = aux[var_a] * aux[var_b]
|
||||
|
||||
# Calculate public input values
|
||||
var_v = 5
|
||||
aux[var_v] = aux[var_w] * (aux[var_a] * aux[var_b]) + \
|
||||
(aux[var_one] - aux[var_w]) * (aux[var_a] + aux[var_b])
|
||||
|
||||
# Just a quick enforcement check:
|
||||
assert aux[var_a] * aux[var_b] == aux[var_m]
|
||||
assert aux[var_w] * (aux[var_m] - aux[var_a] - aux[var_b]) == \
|
||||
aux[var_v] - aux[var_a] - aux[var_b]
|
||||
assert aux[var_w] * aux[var_w] == aux[var_w]
|
||||
|
||||
# Setup the gates. For each row of a, b and c, the statement a b = c holds
|
||||
# R1CS, more info here:
|
||||
# http://www.zeroknowledgeblog.com/index.php/the-pinocchio-protocol/r1cs
|
||||
left = np.full((n, m), fp(0))
|
||||
right = np.full((n, m), fp(0))
|
||||
output = np.full((n, m), fp(0))
|
||||
# ab = m
|
||||
left[0][var_a] = fp(1)
|
||||
right[0][var_b] = fp(1)
|
||||
output[0][var_m] = fp(1)
|
||||
assert aux.dot(left[0]) * aux.dot(right[0]) == aux.dot(output[0])
|
||||
# w(m - a - b) = v - a - b
|
||||
left[1][var_w] = fp(1)
|
||||
right[1][var_m] = fp(1)
|
||||
right[1][var_a] = fp(-1)
|
||||
right[1][var_b] = fp(-1)
|
||||
output[1][var_v] = fp(1)
|
||||
output[1][var_a] = fp(-1)
|
||||
output[1][var_b] = fp(-1)
|
||||
assert aux.dot(left[1]) * aux.dot(right[1]) == aux.dot(output[1])
|
||||
# w^2 = w
|
||||
left[2][var_w] = fp(1)
|
||||
right[2][var_w] = fp(1)
|
||||
output[2][var_w] = fp(1)
|
||||
assert aux.dot(left[2]) * aux.dot(right[2]) == aux.dot(output[2])
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
# See also https://cp-algorithms.com/algebra/fft.html
|
||||
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
P.<X> = K[]
|
||||
|
||||
def get_omega():
|
||||
generator = K(5)
|
||||
assert (q - 1) % 2^32 == 0
|
||||
# Root of unity
|
||||
t = (q - 1) / 2^32
|
||||
omega = generator**t
|
||||
|
||||
assert omega != 1
|
||||
assert omega^(2^16) != 1
|
||||
assert omega^(2^31) != 1
|
||||
assert omega^(2^32) == 1
|
||||
|
||||
return omega
|
||||
|
||||
# Order of this element is 2^32
|
||||
omega = get_omega()
|
||||
k = 3
|
||||
n = 2^k
|
||||
omega = omega^(2^32 / n)
|
||||
assert omega^n == 1
|
||||
|
||||
f = 6*X^7 + 7*X^5 + 3*X^2 + X
|
||||
|
||||
def fft(F):
|
||||
print(f"fft({F})")
|
||||
# On the first invocation:
|
||||
#assert len(F) == n
|
||||
N = len(F)
|
||||
if N == 1:
|
||||
print(" returning 1")
|
||||
return F
|
||||
|
||||
omega_prime = omega^(n/N)
|
||||
assert omega_prime^(n - 1) != 1
|
||||
assert omega_prime^N == 1
|
||||
# Split into even and odd powers of X
|
||||
F_e = [a for a in F[::2]]
|
||||
print(" Evens:", F_e)
|
||||
F_o = [a for a in F[1::2]]
|
||||
print(" Odds:", F_o)
|
||||
|
||||
y_e, y_o = fft(F_e), fft(F_o)
|
||||
print(f"y_e = {y_e}, y_o = {y_o}")
|
||||
y = [0] * N
|
||||
for j in range(N / 2):
|
||||
y[j] = y_e[j] + omega_prime^j * y_o[j]
|
||||
y[j + N / 2] = y_e[j] - omega_prime^j * y_o[j]
|
||||
print(f" returning y = {y}")
|
||||
return y
|
||||
|
||||
print("f =", f)
|
||||
evals = fft(list(f))
|
||||
print("evals =", evals)
|
||||
print("{omega^i : i in {0, 1, ..., n - 1}} =", [omega^i for i in range(n)])
|
||||
evals2 = [f(omega^i) for i in range(n)]
|
||||
print("{f(omega^i) for all omega^i} =", evals2)
|
||||
assert evals == evals2
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../finite_fields/
|
||||
@@ -1,89 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
# Implementation of Groth09 inner product proof
|
||||
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
a = K(0x00)
|
||||
b = K(0x05)
|
||||
E = EllipticCurve(K, (a, b))
|
||||
G = E(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000, 0x02)
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
assert E.order() == p
|
||||
Scalar = GF(p)
|
||||
|
||||
x = np.array([
|
||||
Scalar(110), Scalar(56), Scalar(89), Scalar(6543), Scalar(2)
|
||||
])
|
||||
y = np.array([
|
||||
Scalar(4), Scalar(88), Scalar(14), Scalar(33), Scalar(6)
|
||||
])
|
||||
z = x.dot(y)
|
||||
|
||||
assert len(x) == len(y)
|
||||
|
||||
# Create some generator points. Normally we would use hash to curve.
|
||||
# All these points will be generators since the curve is a cyclic group
|
||||
H = E.random_element()
|
||||
G_vec = [E.random_element() for _ in range(len(x))]
|
||||
|
||||
# We will now construct a proof
|
||||
|
||||
# Commitments
|
||||
|
||||
def dot_product(x, y):
|
||||
result = None
|
||||
for x_i, y_i in zip(x, y):
|
||||
if result is None:
|
||||
result = int(x_i) * y_i
|
||||
else:
|
||||
result += int(x_i) * y_i
|
||||
return result
|
||||
|
||||
t = Scalar.random_element()
|
||||
r = Scalar.random_element()
|
||||
s = Scalar.random_element()
|
||||
|
||||
C_z = int(t) * H + int(z) * G
|
||||
C_x = int(r) * H + dot_product(x, G_vec)
|
||||
C_y = int(s) * H + dot_product(y, G_vec)
|
||||
|
||||
d_x = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
d_y = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
r_d = Scalar.random_element()
|
||||
s_d = Scalar.random_element()
|
||||
|
||||
A_d = int(r_d) * H + dot_product(d_x, G_vec)
|
||||
B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
|
||||
# (cx + d_x)(cy + d_y) = d_x d_y + c(x d_y + y d_x) + c^2 xy
|
||||
t_0 = Scalar.random_element()
|
||||
t_1 = Scalar.random_element()
|
||||
|
||||
C_0 = int(t_0) * H + int(d_x.dot(d_y)) * G
|
||||
C_1 = int(t_1) * H + int(x.dot(d_y) + y.dot(d_x)) * G
|
||||
|
||||
# Challenge
|
||||
# Using the Fiat-Shamir transform, we would hash the transcript
|
||||
|
||||
c = Scalar.random_element()
|
||||
|
||||
# Responses
|
||||
|
||||
f_x = c * x + d_x
|
||||
f_y = c * y + d_y
|
||||
r_x = c * r + r_d
|
||||
s_y = c * s + s_d
|
||||
t_z = c**2 * t + c * t_1 + t_0
|
||||
|
||||
# Verify
|
||||
|
||||
assert int(c) * C_x + A_d == int(r_x) * H + dot_product(f_x, G_vec)
|
||||
assert int(c) * C_y + B_d == int(s_y) * H + dot_product(f_y, G_vec)
|
||||
|
||||
# Actual inner product check
|
||||
# Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
|
||||
|
||||
assert int(t_z) * H + int(f_x.dot(f_y)) * G == int(c**2) * C_z + int(c) * C_1 + C_0
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
|
||||
|
||||
# This file was *autogenerated* from the file groth_poly_commit.sage
|
||||
from sage.all_cmdline import * # import sage library
|
||||
|
||||
_sage_const_0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 = Integer(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001); _sage_const_0x00 = Integer(0x00); _sage_const_0x05 = Integer(0x05); _sage_const_0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 = Integer(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000); _sage_const_0x02 = Integer(0x02); _sage_const_0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001 = Integer(0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001); _sage_const_1000 = Integer(1000); _sage_const_1 = Integer(1); _sage_const_110 = Integer(110); _sage_const_2 = Integer(2); _sage_const_56 = Integer(56); _sage_const_89 = Integer(89); _sage_const_6543 = Integer(6543); _sage_const_0 = Integer(0); _sage_const_77 = Integer(77)
|
||||
import numpy as np
|
||||
from collections import namedtuple
|
||||
|
||||
PolyProof = namedtuple("PolyProof", [
|
||||
"poly_commit",
|
||||
"poly_blind_commit",
|
||||
"poly_response",
|
||||
"poly_blind_respond",
|
||||
"x_blind_factors",
|
||||
"evaluation_commits",
|
||||
"evaluation_response",
|
||||
"value"
|
||||
])
|
||||
|
||||
# Implementation of Groth09 inner product proof
|
||||
|
||||
q = _sage_const_0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
a = K(_sage_const_0x00 )
|
||||
b = K(_sage_const_0x05 )
|
||||
E = EllipticCurve(K, (a, b))
|
||||
G = E(_sage_const_0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 , _sage_const_0x02 )
|
||||
|
||||
p = _sage_const_0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
assert E.order() == p
|
||||
Scalar = GF(p)
|
||||
|
||||
# Create some generator points. Normally we would use hash to curve.
|
||||
# All these points will be generators since the curve is a cyclic group
|
||||
H = E.random_element()
|
||||
G_vec = [E.random_element() for _ in range(_sage_const_1000 )]
|
||||
|
||||
def dot_product(x, y):
|
||||
result = None
|
||||
for x_i, y_i in zip(x, y):
|
||||
if result is None:
|
||||
result = int(x_i) * y_i
|
||||
else:
|
||||
result += int(x_i) * y_i
|
||||
return result
|
||||
|
||||
def poly_commit(p):
|
||||
# Sage randomly orders terms. No guarantee about ordering.
|
||||
#a = np.array(p.coefficients())
|
||||
a = np.array([p[i] for i in range(p.degree() + _sage_const_1 )])
|
||||
r = Scalar.random_element()
|
||||
C_x = int(r) * H + dot_product(a, G_vec)
|
||||
return (r, C_x)
|
||||
|
||||
def create_proof(p, r, x):
|
||||
a = np.array([p[i] for i in range(p.degree() + _sage_const_1 )])
|
||||
#a = np.array(p.coefficients())
|
||||
|
||||
x = np.array([x**i for i in range(p.degree() + _sage_const_1 )])
|
||||
# Evaluate the polynomial
|
||||
z = a.dot(x)
|
||||
|
||||
assert len(a) == len(x)
|
||||
|
||||
# We will now construct a proof
|
||||
|
||||
# Commitments
|
||||
|
||||
t = Scalar.random_element()
|
||||
#r = Scalar.random_element()
|
||||
s = Scalar.random_element()
|
||||
|
||||
C_z = int(t) * H + int(z) * G
|
||||
C_x = int(r) * H + dot_product(a, G_vec)
|
||||
C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
d_x = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
d_y = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
r_d = Scalar.random_element()
|
||||
s_d = Scalar.random_element()
|
||||
|
||||
A_d = int(r_d) * H + dot_product(d_x, G_vec)
|
||||
B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
|
||||
# (cx + d_x)(cy + d_y) = d_x d_y + c(x d_y + y d_x) + c^2 xy
|
||||
t_0 = Scalar.random_element()
|
||||
t_1 = Scalar.random_element()
|
||||
|
||||
C_0 = int(t_0) * H + int(d_x.dot(d_y)) * G
|
||||
C_1 = int(t_1) * H + int(a.dot(d_y) + x.dot(d_x)) * G
|
||||
|
||||
# Challenge
|
||||
# Using the Fiat-Shamir transform, we would hash the transcript
|
||||
|
||||
#c = Scalar.random_element()
|
||||
c = _sage_const_110
|
||||
|
||||
# Responses
|
||||
|
||||
f_x = c * a + d_x
|
||||
f_y = c * x + d_y
|
||||
r_x = c * r + r_d
|
||||
s_y = c * s + s_d
|
||||
t_z = c**_sage_const_2 * t + c * t_1 + t_0
|
||||
|
||||
# Verify
|
||||
|
||||
#B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
#C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
assert int(c) * C_x + A_d == int(r_x) * H + dot_product(f_x, G_vec)
|
||||
assert int(c) * C_y + B_d == int(s_y) * H + dot_product(f_y, G_vec)
|
||||
|
||||
# Actual inner product check
|
||||
# Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
|
||||
|
||||
assert int(t_z) * H + int(f_x.dot(f_y)) * G == int(c**_sage_const_2 ) * C_z + int(c) * C_1 + C_0
|
||||
|
||||
return PolyProof(
|
||||
poly_commit=C_x,
|
||||
poly_blind_commit=A_d,
|
||||
poly_response=f_x,
|
||||
poly_blind_respond=r_x,
|
||||
x_blind_factors=(s_d, d_y, s),
|
||||
evaluation_commits=(C_0, C_1, C_z),
|
||||
evaluation_response=t_z,
|
||||
value=z
|
||||
)
|
||||
|
||||
def verify_proof(proof, x):
|
||||
C_x = proof.poly_commit
|
||||
A_d = proof.poly_blind_commit
|
||||
f_x = proof.poly_response
|
||||
r_x = proof.poly_blind_respond
|
||||
(s_d, d_y, s) = proof.x_blind_factors
|
||||
(C_0, C_1, C_z) = proof.evaluation_commits
|
||||
t_z = proof.evaluation_response
|
||||
z = proof.value
|
||||
|
||||
x = np.array([x**i for i in range(len(a))])
|
||||
c = _sage_const_110
|
||||
|
||||
f_y = c * x + d_y
|
||||
s_y = c * s + s_d
|
||||
B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
if int(c) * C_x + A_d != int(r_x) * H + dot_product(f_x, G_vec):
|
||||
return False
|
||||
if int(c) * C_y + B_d != int(s_y) * H + dot_product(f_y, G_vec):
|
||||
return False
|
||||
|
||||
# Actual inner product check
|
||||
# Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
|
||||
|
||||
if int(t_z) * H + int(f_x.dot(f_y)) * G != int(c**_sage_const_2 ) * C_z + int(c) * C_1 + C_0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
#R = LaurentPolynomialRing(Scalar, names=('x',)); (x,) = R._first_ngens(1)
|
||||
#a = np.array([
|
||||
# Scalar(_sage_const_110 ), Scalar(_sage_const_56 ), Scalar(_sage_const_89 ), Scalar(_sage_const_6543 ), Scalar(_sage_const_2 )
|
||||
#])
|
||||
#p = _sage_const_0
|
||||
#for i, a_i in enumerate(a):
|
||||
# p += a_i * x**i
|
||||
#print(p)
|
||||
#xx = Scalar(_sage_const_77 )
|
||||
#r, commit = poly_commit(p)
|
||||
#proof = create_proof(p, r, xx)
|
||||
#assert verify_proof(proof, xx)
|
||||
#assert proof.poly_commit == commit
|
||||
#assert proof.value == p(xx)
|
||||
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
import numpy as np
|
||||
from collections import namedtuple
|
||||
|
||||
PolyProof = namedtuple("PolyProof", [
|
||||
"poly_commit",
|
||||
"poly_blind_commit",
|
||||
"poly_response",
|
||||
"poly_blind_respond",
|
||||
"x_blind_factors",
|
||||
"evaluation_commits",
|
||||
"evaluation_response",
|
||||
"value"
|
||||
])
|
||||
|
||||
# Implementation of Groth09 inner product proof
|
||||
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
a = K(0x00)
|
||||
b = K(0x05)
|
||||
E = EllipticCurve(K, (a, b))
|
||||
G = E(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000, 0x02)
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
assert E.order() == p
|
||||
Scalar = GF(p)
|
||||
|
||||
# Create some generator points. Normally we would use hash to curve.
|
||||
# All these points will be generators since the curve is a cyclic group
|
||||
H = E.random_element()
|
||||
G_vec = [E.random_element() for _ in range(1000)]
|
||||
|
||||
def dot_product(x, y):
|
||||
result = None
|
||||
for x_i, y_i in zip(x, y):
|
||||
if result is None:
|
||||
result = int(x_i) * y_i
|
||||
else:
|
||||
result += int(x_i) * y_i
|
||||
return result
|
||||
|
||||
def poly_commit(p):
|
||||
# Sage randomly orders terms. No guarantee about ordering.
|
||||
#a = np.array(p.coefficients())
|
||||
a = np.array([p[i] for i in range(p.degree() + 1)])
|
||||
r = Scalar.random_element()
|
||||
C_x = int(r) * H + dot_product(a, G_vec)
|
||||
return (r, C_x)
|
||||
|
||||
def create_proof(p, r, x):
|
||||
a = np.array([p[i] for i in range(p.degree() + 1)])
|
||||
#a = np.array(p.coefficients())
|
||||
|
||||
x = np.array([x**i for i in range(p.degree() + 1)])
|
||||
# Evaluate the polynomial
|
||||
z = a.dot(x)
|
||||
|
||||
assert len(a) == len(x)
|
||||
|
||||
# We will now construct a proof
|
||||
|
||||
# Commitments
|
||||
|
||||
t = Scalar.random_element()
|
||||
#r = Scalar.random_element()
|
||||
s = Scalar.random_element()
|
||||
|
||||
C_z = int(t) * H + int(z) * G
|
||||
C_x = int(r) * H + dot_product(a, G_vec)
|
||||
C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
d_x = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
d_y = np.array([Scalar.random_element() for _ in range(len(x))])
|
||||
r_d = Scalar.random_element()
|
||||
s_d = Scalar.random_element()
|
||||
|
||||
A_d = int(r_d) * H + dot_product(d_x, G_vec)
|
||||
B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
|
||||
# (cx + d_x)(cy + d_y) = d_x d_y + c(x d_y + y d_x) + c^2 xy
|
||||
t_0 = Scalar.random_element()
|
||||
t_1 = Scalar.random_element()
|
||||
|
||||
C_0 = int(t_0) * H + int(d_x.dot(d_y)) * G
|
||||
C_1 = int(t_1) * H + int(a.dot(d_y) + x.dot(d_x)) * G
|
||||
|
||||
# Challenge
|
||||
# Using the Fiat-Shamir transform, we would hash the transcript
|
||||
|
||||
#c = Scalar.random_element()
|
||||
c = 110
|
||||
|
||||
# Responses
|
||||
|
||||
f_x = c * a + d_x
|
||||
f_y = c * x + d_y
|
||||
r_x = c * r + r_d
|
||||
s_y = c * s + s_d
|
||||
t_z = c**2 * t + c * t_1 + t_0
|
||||
|
||||
# Verify
|
||||
|
||||
#B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
#C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
assert int(c) * C_x + A_d == int(r_x) * H + dot_product(f_x, G_vec)
|
||||
assert int(c) * C_y + B_d == int(s_y) * H + dot_product(f_y, G_vec)
|
||||
|
||||
# Actual inner product check
|
||||
# Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
|
||||
|
||||
assert int(t_z) * H + int(f_x.dot(f_y)) * G == int(c**2) * C_z + int(c) * C_1 + C_0
|
||||
|
||||
return PolyProof(
|
||||
poly_commit=C_x,
|
||||
poly_blind_commit=A_d,
|
||||
poly_response=f_x,
|
||||
poly_blind_respond=r_x,
|
||||
x_blind_factors=(s_d, d_y, s),
|
||||
evaluation_commits=(C_0, C_1, C_z),
|
||||
evaluation_response=t_z,
|
||||
value=z
|
||||
)
|
||||
|
||||
def verify_proof(proof, x):
|
||||
C_x = proof.poly_commit
|
||||
A_d = proof.poly_blind_commit
|
||||
f_x = proof.poly_response
|
||||
r_x = proof.poly_blind_respond
|
||||
(s_d, d_y, s) = proof.x_blind_factors
|
||||
(C_0, C_1, C_z) = proof.evaluation_commits
|
||||
t_z = proof.evaluation_response
|
||||
z = proof.value
|
||||
|
||||
x = np.array([x**i for i in range(len(a))])
|
||||
c = 110
|
||||
|
||||
f_y = c * x + d_y
|
||||
s_y = c * s + s_d
|
||||
B_d = int(s_d) * H + dot_product(d_y, G_vec)
|
||||
C_y = int(s) * H + dot_product(x, G_vec)
|
||||
|
||||
if int(c) * C_x + A_d != int(r_x) * H + dot_product(f_x, G_vec):
|
||||
return False
|
||||
if int(c) * C_y + B_d != int(s_y) * H + dot_product(f_y, G_vec):
|
||||
return False
|
||||
|
||||
# Actual inner product check
|
||||
# Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
|
||||
|
||||
if int(t_z) * H + int(f_x.dot(f_y)) * G != int(c**2) * C_z + int(c) * C_1 + C_0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
R.<x> = LaurentPolynomialRing(Scalar)
|
||||
a = np.array([
|
||||
Scalar(110), Scalar(56), Scalar(89), Scalar(6543), Scalar(2)
|
||||
])
|
||||
p = 0
|
||||
for i, a_i in enumerate(a):
|
||||
p += a_i * x**i
|
||||
print(p)
|
||||
xx = Scalar(77)
|
||||
r, commit = poly_commit(p)
|
||||
proof = create_proof(p, r, xx)
|
||||
assert verify_proof(proof, xx)
|
||||
assert proof.poly_commit == commit
|
||||
assert proof.value == p(xx)
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
import numpy as np
|
||||
from groth_poly_commit import Scalar, poly_commit, create_proof, verify_proof
|
||||
|
||||
K = Scalar
|
||||
# Just use the same finite field we put in the polynomial commitment scheme file
|
||||
#p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
#K = FiniteField(p)
|
||||
R.<x, y> = LaurentPolynomialRing(K)
|
||||
|
||||
var_one = K(1)
|
||||
var_x = K(4)
|
||||
var_y = K(6)
|
||||
var_s = K(1)
|
||||
var_xy = var_x * var_y
|
||||
var_sxy = var_s * var_xy
|
||||
var_1_neg_s = var_one - var_s
|
||||
var_x_y = var_x + var_y
|
||||
var_1_neg_s_x_y = var_1_neg_s * var_x_y
|
||||
var_s_neg_1 = -var_1_neg_s
|
||||
var_zero = K(0)
|
||||
|
||||
public_v = var_s * (var_x * var_y) + (1 - var_s) * (var_x + var_y)
|
||||
|
||||
a = np.array([
|
||||
var_one, var_x, var_xy, var_1_neg_s, var_s
|
||||
])
|
||||
b = np.array([
|
||||
var_one, var_y, var_s, var_x_y, var_s_neg_1
|
||||
])
|
||||
c = np.array([
|
||||
var_one, var_xy, var_sxy, var_1_neg_s_x_y, var_zero
|
||||
])
|
||||
assert len(a) == len(b)
|
||||
assert len(b) == len(c)
|
||||
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
try:
|
||||
assert a_i * b_i == c_i
|
||||
except AssertionError:
|
||||
print("Error for %i" % i)
|
||||
raise
|
||||
|
||||
# 1 - s = -(s - 1)
|
||||
u1 = np.array([0, 0, 0, 1, 0])
|
||||
v1 = np.array([0, 0, 0, 0, 1])
|
||||
w1 = np.array([0, 0, 0, 0, 0])
|
||||
k1 = 0
|
||||
|
||||
assert a.dot(u1) + b.dot(v1) + c.dot(w1) == k1
|
||||
|
||||
# xy = xy
|
||||
u2 = np.array([0, 0, 1, 0, 0])
|
||||
v2 = np.array([0, 0, 0, 0, 0])
|
||||
w2 = np.array([0, -1, 0, 0, 0])
|
||||
k2 = 0
|
||||
|
||||
assert a.dot(u2) + b.dot(v2) + c.dot(w2) == k2
|
||||
|
||||
# s = s
|
||||
u3 = np.array([0, 0, 0, 0, -1])
|
||||
v3 = np.array([0, 0, 1, 0, 0])
|
||||
w3 = np.array([0, 0, 0, 0, 0])
|
||||
k3 = 0
|
||||
|
||||
assert a.dot(u3) + b.dot(v3) + c.dot(w3) == k3
|
||||
|
||||
# zero = 0
|
||||
u4 = np.array([0, 0, 0, 0, 0])
|
||||
v4 = np.array([0, 0, 0, 0, 0])
|
||||
w4 = np.array([0, 0, 0, 0, 1])
|
||||
k4 = 0
|
||||
|
||||
assert a.dot(u4) + b.dot(v4) + c.dot(w4) == k4
|
||||
|
||||
# 1 - s
|
||||
u5 = np.array([1, 0, 0, -1, 0])
|
||||
v5 = np.array([0, 0, -1, 0, 0])
|
||||
w5 = np.array([0, 0, 0, 0, 0])
|
||||
k5 = 0
|
||||
|
||||
assert a.dot(u5) + b.dot(v5) + c.dot(w5) == k5
|
||||
|
||||
# x + y
|
||||
u6 = np.array([0, 1, 0, 0, 0])
|
||||
v6 = np.array([0, 1, 0, -1, 0])
|
||||
w6 = np.array([0, 0, 0, 0, 0])
|
||||
k6 = 0
|
||||
|
||||
assert a.dot(u6) + b.dot(v6) + c.dot(w6) == k6
|
||||
|
||||
# Final check:
|
||||
# v = s(xy) + (1 - s)(x + y)
|
||||
u7 = np.array([0, 0, 0, 0, 0])
|
||||
v7 = np.array([0, 0, 0, 0, 0])
|
||||
w7 = np.array([0, 0, 1, 1, 0])
|
||||
k7 = public_v
|
||||
|
||||
assert a.dot(u7) + b.dot(v7) + c.dot(w7) == k7
|
||||
|
||||
u = np.vstack((u1, u2, u3, u4, u5, u6, u7))
|
||||
v = np.vstack((v1, v2, v3, v4, v5, v6, v7))
|
||||
w = np.vstack((w1, w2, w3, w4, w5, w6, w7))
|
||||
assert u.shape == v.shape
|
||||
assert u.shape == w.shape
|
||||
|
||||
k = np.array((k1, k2, k3, k4, k5, k6, k7))
|
||||
|
||||
p = K(0)
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
#print(a_i, "\t", b_i, "\t", c_i)
|
||||
p += y**i * (a_i * b_i - c_i)
|
||||
print(p)
|
||||
|
||||
p = K(0)
|
||||
for q, (u_q, v_q, w_q, k_q) in enumerate(zip(u, v, w, k)):
|
||||
p += y**q * (a.dot(u_q) + b.dot(v_q) + c.dot(w_q) - k_q)
|
||||
print(p)
|
||||
|
||||
n = len(a)
|
||||
assert len(b) == n
|
||||
assert len(c) == n
|
||||
|
||||
assert u.shape == (7, n)
|
||||
assert v.shape == u.shape
|
||||
assert w.shape == u.shape
|
||||
assert k.shape == (7,)
|
||||
|
||||
r_x_y = 0
|
||||
s_x_y = 0
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
assert 1 <= i <= n
|
||||
|
||||
r_x_y += x**i * y**i * a_i
|
||||
r_x_y += x**-i * y**-i * b_i
|
||||
r_x_y += x**(-i - n) * y**(-i - n) * c_i
|
||||
|
||||
u_i = u.T[i - 1]
|
||||
v_i = v.T[i - 1]
|
||||
w_i = w.T[i - 1]
|
||||
u_i_Y = 0
|
||||
v_i_Y = 0
|
||||
w_i_Y = 0
|
||||
for q, (u_q_i, v_q_i, w_q_i) in enumerate(zip(u_i, v_i, w_i), 1):
|
||||
assert 1 <= q <= 7
|
||||
|
||||
u_i_Y += y**q * u_q_i
|
||||
v_i_Y += y**q * v_q_i
|
||||
w_i_Y += y**q * w_q_i
|
||||
|
||||
s_x_y += u_i_Y * x**-i + v_i_Y * x**i + w_i_Y * x**(i + n)
|
||||
|
||||
k_y = 0
|
||||
for q, k_q in enumerate(k, 1):
|
||||
assert 1 <= q <= 7
|
||||
k_y += y**q * k_q
|
||||
|
||||
# Section 6, Figure 2
|
||||
#
|
||||
# zkP1
|
||||
# 4 blinding factors since we evaluate r(X, Y) 3 times
|
||||
# Blind r(X, Y)
|
||||
for i in range(1, 4 + 1):
|
||||
blind_c_i = K.random_element()
|
||||
r_x_y += x**(-2*n - i) * y**(-2*n - i) * blind_c_i
|
||||
|
||||
# Commit to r(X, Y)
|
||||
|
||||
s_prime_x_y = y**n * s_x_y
|
||||
for i in range(1, n):
|
||||
s_prime_x_y -= (y**i + y**-i) * x**(i + n)
|
||||
|
||||
r_x_1 = r_x_y(y=K(1))
|
||||
t_x_y = r_x_1 * (r_x_y + s_prime_x_y) - y**n * k_y
|
||||
|
||||
# This can be opened to r(X, Y) since r(X, Y) = r(XY, 1)
|
||||
r_x_1_scaled = (r_x_1 * x**(3*n - 1)).univariate_polynomial()
|
||||
rx1_commit_blind, rx1_commit = poly_commit(r_x_1_scaled)
|
||||
|
||||
print("===================")
|
||||
print(" t(X, Y)")
|
||||
print("===================")
|
||||
|
||||
power_dict = ["⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"]
|
||||
|
||||
def superscript(number):
|
||||
sign = ""
|
||||
if number < 0:
|
||||
sign = "⁻"
|
||||
number = -number
|
||||
return sign + "".join([power_dict[int(digit)] for digit in list(str(number))])
|
||||
|
||||
decorated = []
|
||||
for (x_power, y_power), coeff in t_x_y.dict().items():
|
||||
if coeff == 1:
|
||||
coeff = ""
|
||||
display = "%s X%s Y%s" % (coeff, superscript(x_power), superscript(y_power))
|
||||
decorated.append([x_power, y_power, display])
|
||||
decorated.sort(key=lambda x: (x[0], -x[1]))
|
||||
for _, _, display in decorated:
|
||||
print(display)
|
||||
print()
|
||||
print("Constant coefficient:", t_x_y.constant_coefficient())
|
||||
print()
|
||||
|
||||
# zkV1
|
||||
# Send a random y
|
||||
challenge_y = K.random_element()
|
||||
|
||||
# zkP2
|
||||
# Commit to t(X, y)
|
||||
t_x = t_x_y(y=challenge_y)
|
||||
t_x = t_x.univariate_polynomial()
|
||||
print("===================")
|
||||
print(" t(X, y)")
|
||||
print("===================")
|
||||
print(t_x.dict())
|
||||
print()
|
||||
print("Constant coefficient:", t_x.constant_coefficient())
|
||||
|
||||
# Split the polynomial into low and hi versions
|
||||
t_lo_x = 0
|
||||
t_hi_x = 0
|
||||
smallest_power = -min(t_x.dict().keys())
|
||||
for power, coeff in t_x.dict().items():
|
||||
assert power != 0
|
||||
if power < 0:
|
||||
t_lo_x += x**(smallest_power + power) * coeff
|
||||
else:
|
||||
t_hi_x += x**(power - 1) * coeff
|
||||
d = t_lo_x.degree() + 1
|
||||
t_lo_x = t_lo_x.univariate_polynomial()
|
||||
t_hi_x = t_hi_x.univariate_polynomial()
|
||||
assert (t_lo_x * x**-d + t_hi_x * x).univariate_polynomial() == t_x
|
||||
|
||||
T_lo_commit_blind, T_lo = poly_commit(t_lo_x)
|
||||
T_hi_commit_blind, T_hi = poly_commit(t_hi_x)
|
||||
|
||||
# zkV2
|
||||
# Send a random z
|
||||
challenge_z = K.random_element()
|
||||
|
||||
# zkP3
|
||||
# Evaluate a = r(z, 1)
|
||||
a = r_x_y(x=challenge_z, y=K(1))
|
||||
# Evaluate b = r(z, y)
|
||||
b = r_x_y(x=challenge_z, y=challenge_y)
|
||||
# Evaluate t = t(z, y)
|
||||
t = t_x_y(x=challenge_z, y=challenge_y)
|
||||
# Evaluate s = s(z, y)
|
||||
s = s_prime_x_y(x=challenge_z, y=challenge_y)
|
||||
|
||||
# Calculate equivalent openings
|
||||
# s'(X, Y) is known by both prover and verifier
|
||||
a_proof = create_proof(r_x_1_scaled, rx1_commit_blind, challenge_z)
|
||||
assert a_proof.poly_commit == rx1_commit
|
||||
b_proof = create_proof(r_x_1_scaled, rx1_commit_blind, challenge_y * challenge_z)
|
||||
assert b_proof.poly_commit == rx1_commit
|
||||
t_proof_lo = create_proof(t_lo_x, T_lo_commit_blind, challenge_z)
|
||||
assert t_proof_lo.poly_commit == T_lo
|
||||
t_proof_hi = create_proof(t_hi_x, T_hi_commit_blind, challenge_z)
|
||||
assert t_proof_hi.poly_commit == T_hi
|
||||
|
||||
# Signature of correct computation not yet implemented
|
||||
# So just use s for now as is
|
||||
|
||||
# Scaling factor
|
||||
verifier_rescale = challenge_z**(-3*n + 1)
|
||||
assert a_proof.value * verifier_rescale == a
|
||||
verifier_rescale = (challenge_y * challenge_z)**(-3*n + 1)
|
||||
assert b_proof.value * verifier_rescale == b
|
||||
|
||||
# zkV3
|
||||
# Recalculate t from a, b and s
|
||||
t_new = t_proof_lo.value * challenge_z**-d + t_proof_hi.value * challenge_z
|
||||
assert t_new == t
|
||||
t = t_new
|
||||
|
||||
k = (y**n * k_y)(y=challenge_y)
|
||||
t_new = a * (b + s) - k
|
||||
assert t_new == t
|
||||
# Verify polynomial commitments
|
||||
|
||||
@@ -1,347 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
P.<X> = K[]
|
||||
|
||||
# GENERATOR^{2^s} where t * 2^s + 1 = q with t odd.
|
||||
# In other words, this is a t root of unity.
|
||||
generator = K(5)
|
||||
# There is a large 2^32 order subgroup in this curve because it is 2-adic
|
||||
t = (K(q) - 1) / 2^32
|
||||
assert int(t) % 2 != 0
|
||||
delta = generator^(2^32)
|
||||
assert delta^t == 1
|
||||
|
||||
# The size of the multiplicative group is phi(q) = q - 1
|
||||
# And inside this group are 2 distinct subgroups of size t and 2^s.
|
||||
# delta is the generator for the size t subgroup, and omega for the 2^s one.
|
||||
# Taking powers of these generators and multiplying them will produce
|
||||
# unique cosets that divide the entire group for q.
|
||||
|
||||
def get_omega():
|
||||
generator = K(5)
|
||||
assert (q - 1) % 2^32 == 0
|
||||
# Root of unity
|
||||
t = (q - 1) / 2^32
|
||||
omega = generator**t
|
||||
|
||||
assert omega != 1
|
||||
assert omega^(2^16) != 1
|
||||
assert omega^(2^31) != 1
|
||||
assert omega^(2^32) == 1
|
||||
|
||||
return omega
|
||||
|
||||
# Order of this element is 2^32
|
||||
omega = get_omega()
|
||||
k = 4
|
||||
n = 2^k
|
||||
omega = omega^(2^32 / n)
|
||||
assert omega^n == 1
|
||||
|
||||
# Arithmetization for:
|
||||
# sxy + (s - 1)(x + y) - z = 0
|
||||
# s(s - 1) = 0
|
||||
|
||||
# F1(A1 - 1) + F2 (A1 - I) + F3((1 - A1)(A2 + A3) - A4) + F4(A1 A2 A3 - A4) = 0
|
||||
A = []
|
||||
F = []
|
||||
|
||||
var_zero = K(0)
|
||||
var_x = K(4)
|
||||
var_y = K(6)
|
||||
var_s = K(1)
|
||||
var_sxy = var_s * var_x * var_y
|
||||
var_1s_xy = (1 - var_s) * (var_x + var_y)
|
||||
# Public
|
||||
var_z = var_sxy + var_1s_xy
|
||||
|
||||
# 4 advice columns
|
||||
# 4 fixed columns
|
||||
# 1 instance column
|
||||
|
||||
# Row 1
|
||||
# z = public z
|
||||
A_1_1, A_2_1, A_3_1, A_4_1 = var_z, 0, 0, 0
|
||||
F_1_1, F_2_1, F_3_1, F_4_1 = 1, 0, 0, 0
|
||||
I_1 = var_z
|
||||
|
||||
# Row 2
|
||||
# ~0 == 0
|
||||
A_1_2, A_2_2, A_3_2, A_4_2 = var_zero, 0, 0, 0
|
||||
F_1_2, F_2_2, F_3_2, F_4_2 = 0, 1, 0, 0
|
||||
I_2 = 0
|
||||
|
||||
# Row 3
|
||||
# Boolean check
|
||||
# (1 - s)(s + 0) == 0
|
||||
A_1_3, A_2_3, A_3_3, A_4_3 = var_s, var_s, var_zero, var_zero
|
||||
F_1_3, F_2_3, F_3_3, F_4_3 = 0, 0, 1, 0
|
||||
I_3 = 0
|
||||
|
||||
# Row 4
|
||||
# s x y == sxy
|
||||
A_1_4, A_2_4, A_3_4, A_4_4 = var_s, var_x, var_y, var_sxy
|
||||
F_1_4, F_2_4, F_3_4, F_4_4 = 0, 0, 0, 1
|
||||
I_4 = 0
|
||||
|
||||
# Row 5
|
||||
# (1 - s)(x + y) = (1-s)(x+y)
|
||||
A_1_5, A_2_5, A_3_5, A_4_5 = var_s, var_x, var_y, var_1s_xy
|
||||
F_1_5, F_2_5, F_3_5, F_4_5 = 0, 0, 1, 0
|
||||
I_5 = 0
|
||||
|
||||
# Row 6
|
||||
# (1 - 0)(sxy + (1-s)(x+y)) = z
|
||||
A_1_6, A_2_6, A_3_6, A_4_6 = var_zero, var_sxy, var_1s_xy, var_z
|
||||
F_1_6, F_2_6, F_3_6, F_4_6 = 0, 0, 1, 0
|
||||
I_6 = 0
|
||||
|
||||
A1 = [A_1_1, A_1_2, A_1_3, A_1_4, A_1_5, A_1_6]
|
||||
A2 = [A_2_1, A_2_2, A_2_3, A_2_4, A_2_5, A_2_6]
|
||||
A3 = [A_3_1, A_3_2, A_3_3, A_3_4, A_3_5, A_3_6]
|
||||
A4 = [A_4_1, A_4_2, A_4_3, A_4_4, A_4_5, A_4_6]
|
||||
F1 = [F_1_1, F_1_2, F_1_3, F_1_4, F_1_5, F_1_6]
|
||||
F2 = [F_2_1, F_2_2, F_2_3, F_2_4, F_2_5, F_2_6]
|
||||
F3 = [F_3_1, F_3_2, F_3_3, F_3_4, F_3_5, F_3_6]
|
||||
F4 = [F_4_1, F_4_2, F_4_3, F_4_4, F_4_5, F_4_6]
|
||||
I = [I_1, I_2, I_3, I_4, I_5, I_6]
|
||||
|
||||
# There should be 5 unused blinding rows.
|
||||
# see src/plonk/circuit.rs: fn blinding_factors(&self) -> usize;
|
||||
# We have 9 so we are perfectly fine.
|
||||
|
||||
# Add 9 empty rows
|
||||
assert n - len(A1) == 10
|
||||
for i in range(10):
|
||||
A1.append(K.random_element())
|
||||
A2.append(K.random_element())
|
||||
A3.append(K.random_element())
|
||||
A4.append(K.random_element())
|
||||
F1.append(0)
|
||||
F2.append(0)
|
||||
F3.append(0)
|
||||
F4.append(0)
|
||||
I.append(K.random_element())
|
||||
|
||||
assert (len(A1) == len(A2) == len(A3) == len(A4) == len(F1) == len(F2)
|
||||
== len(F3) == len(F4) == len(I) == n)
|
||||
|
||||
for A_1_i, A_2_i, A_3_i, A_4_i, F_1_i, F_2_i, F_3_i, F_4_i, I_i in zip(
|
||||
A1, A2, A3, A4, F1, F2, F3, F4, I):
|
||||
assert (F_1_i * (A_1_i - I_i)
|
||||
+ F_2_i * A_1_i
|
||||
+ F_3_i * ((1 - A_1_i) * (A_2_i + A_3_i) - A_4_i)
|
||||
+ F_4_i * (A_1_i * A_2_i * A_3_i - A_4_i)) == 0
|
||||
|
||||
a_1_X = P.lagrange_polynomial((omega^i, A_1_i) for i, A_1_i in enumerate(A1))
|
||||
a_2_X = P.lagrange_polynomial((omega^i, A_2_i) for i, A_2_i in enumerate(A2))
|
||||
a_3_X = P.lagrange_polynomial((omega^i, A_3_i) for i, A_3_i in enumerate(A3))
|
||||
a_4_X = P.lagrange_polynomial((omega^i, A_4_i) for i, A_4_i in enumerate(A4))
|
||||
f_1_X = P.lagrange_polynomial((omega^i, F_1_i) for i, F_1_i in enumerate(F1))
|
||||
f_2_X = P.lagrange_polynomial((omega^i, F_2_i) for i, F_2_i in enumerate(F2))
|
||||
f_3_X = P.lagrange_polynomial((omega^i, F_3_i) for i, F_3_i in enumerate(F3))
|
||||
f_4_X = P.lagrange_polynomial((omega^i, F_4_i) for i, F_4_i in enumerate(F4))
|
||||
# Treat the instance wire as a 5th advice wire
|
||||
a_5_X = P.lagrange_polynomial((omega^i, A_5_i) for i, A_5_i in enumerate(I))
|
||||
|
||||
for i, (A_1_i, A_2_i, A_3_i, A_4_i, F_1_i, F_2_i, F_3_i, F_4_i, I_i) in \
|
||||
enumerate(zip(A1, A2, A3, A4, F1, F2, F3, F4, I)):
|
||||
assert a_1_X(omega^i) == A_1_i
|
||||
assert a_2_X(omega^i) == A_2_i
|
||||
assert a_3_X(omega^i) == A_3_i
|
||||
assert a_4_X(omega^i) == A_4_i
|
||||
assert a_5_X(omega^i) == I_i
|
||||
assert f_1_X(omega^i) == F_1_i
|
||||
assert f_2_X(omega^i) == F_2_i
|
||||
assert f_3_X(omega^i) == F_3_i
|
||||
assert f_4_X(omega^i) == F_4_i
|
||||
|
||||
# beta, gamma
|
||||
beta = K.random_element()
|
||||
gamma = K.random_element()
|
||||
|
||||
# 0 1 2 3 4 5 ... 15
|
||||
# A1: z, 0, s, s, s, 0,
|
||||
#
|
||||
# 16 17 18 19 20 21 ... 31
|
||||
# A2: -, -, s, x, x, sxy,
|
||||
#
|
||||
# 32 33 34 35 36 37 ... 47
|
||||
# A3: -, -, 0, y, y, (1-s)(x+y),
|
||||
#
|
||||
# 48 49 50 51 52 53 ... 63
|
||||
# A4: -, -, 0, sxy, (1-s)(x + y), z,
|
||||
#
|
||||
# 64 65 66 67 68 69 ... 79
|
||||
# A5: z, -, -, -, -, -,
|
||||
|
||||
# z = (0 53 64)
|
||||
# 0 = (1 5 34 50)
|
||||
# s = (2 3 4 18)
|
||||
# x = (19 20)
|
||||
# sxy = (21 51)
|
||||
# y = (35 36)
|
||||
# (1-s)(x+y) = (37 52)
|
||||
|
||||
permuted_indices = list(range(n * 5))
|
||||
assert len(permuted_indices) == 80
|
||||
|
||||
# Apply the actual permutation cycles
|
||||
# z
|
||||
permuted_indices[0] = 53
|
||||
permuted_indices[53] = 64
|
||||
permuted_indices[64] = 0
|
||||
# ~0
|
||||
permuted_indices[1] = 5
|
||||
permuted_indices[5] = 34
|
||||
permuted_indices[34] = 50
|
||||
permuted_indices[50] = 1
|
||||
# s
|
||||
permuted_indices[2] = 3
|
||||
permuted_indices[3] = 4
|
||||
permuted_indices[4] = 18
|
||||
permuted_indices[18] = 2
|
||||
# x
|
||||
permuted_indices[19] = 20
|
||||
permuted_indices[20] = 19
|
||||
# sxy
|
||||
permuted_indices[21] = 51
|
||||
permuted_indices[51] = 21
|
||||
# y
|
||||
permuted_indices[35] = 36
|
||||
permuted_indices[36] = 35
|
||||
# (1-s)(x+y)
|
||||
permuted_indices[37] = 52
|
||||
permuted_indices[52] = 37
|
||||
|
||||
witness = A1 + A2 + A3 + A4 + I
|
||||
for i, val in enumerate(witness):
|
||||
assert val == witness[permuted_indices[i]]
|
||||
|
||||
# How to join lists together?
|
||||
indices = ([omega^i for i in range(n)]
|
||||
+ [delta * omega^i for i in range(n)]
|
||||
+ [delta^2 * omega^i for i in range(n)]
|
||||
+ [delta^3 * omega^i for i in range(n)]
|
||||
+ [delta^4 * omega^i for i in range(n)])
|
||||
assert len(indices) == 80
|
||||
# Permuted indices
|
||||
sigma_star = [indices[i] for i in permuted_indices]
|
||||
s = [sigma_star[:n], sigma_star[n:2 * n], sigma_star[2 * n:3 * n],
|
||||
sigma_star[3 * n:4 * n], sigma_star[4 * n:]]
|
||||
assert s[0] + s[1] + s[2] + s[3] + s[4] == sigma_star
|
||||
v = [A1, A2, A3, A4, I]
|
||||
|
||||
# We split the columns into sets of size m.
|
||||
# Here we will use m = 1 for illustration purposes
|
||||
|
||||
# We have 6 usable rows
|
||||
# n = 16 rows total
|
||||
# row u (q_last) will be the 7th row
|
||||
# So we have 9 unusable rows
|
||||
q_blind = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
q_last = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
# Turn both of these into polynomial form
|
||||
q_blind = P.lagrange_polynomial((omega^i, q_i) for i, q_i in enumerate(q_blind))
|
||||
assert q_blind(omega^5) == 0
|
||||
assert q_blind(omega^6) == 0
|
||||
assert q_blind(omega^7) == 1
|
||||
assert q_blind(omega^11) == 1
|
||||
q_last = P.lagrange_polynomial((omega^i, q_i) for i, q_i in enumerate(q_last))
|
||||
assert q_last(omega^5) == 0
|
||||
assert q_last(omega^6) == 1
|
||||
assert q_last(omega^7) == 0
|
||||
assert q_last(omega^11) == 0
|
||||
|
||||
m = 5
|
||||
assert n == 16
|
||||
# 6 usable rows
|
||||
u = 6
|
||||
# There are 5 columns
|
||||
# We will split the columns partitions into 5 partitions to make things easy
|
||||
# So b = 5, and each partition contains only a single column
|
||||
# We still iterate over the column to make it more obvious
|
||||
m = 1
|
||||
permutation_points = [(1, 1)]
|
||||
last_y_value = 1
|
||||
ZP = []
|
||||
# a is the current column partition we are aggregating
|
||||
for a in range(5):
|
||||
# j iterates over the rows
|
||||
for j in range(u):
|
||||
current = last_y_value
|
||||
|
||||
# i iterates over the columns in our partition
|
||||
for i in range(a * m, (a + 1)):
|
||||
current *= v[i][j] + beta * delta^i * omega^j + gamma
|
||||
current /= v[i][j] + beta * s[i][j] + gamma
|
||||
|
||||
last_y_value = current
|
||||
permutation_points.append((omega^(j + 1), current))
|
||||
|
||||
ZP_a = P.lagrange_polynomial(permutation_points)
|
||||
ZP.append(ZP_a)
|
||||
permutation_points = [(1, last_y_value)]
|
||||
|
||||
# l_0(X) (1 - ZP,0(X)) = 0
|
||||
# => ZP,0(1) = 1
|
||||
assert ZP[0](1) == 1
|
||||
# Checks for l_0(X) (ZP,a(X) - ZP,a-1(omega^u X)) = 1
|
||||
# => ZP,a(Z) = ZP,a-1(omega^u X)
|
||||
# This copies the end value from one partition to the next one
|
||||
assert ZP[1](omega^0) == ZP[0](omega^u)
|
||||
assert ZP[2](omega^0) == ZP[1](omega^u)
|
||||
assert ZP[3](omega^0) == ZP[2](omega^u)
|
||||
assert ZP[4](omega^0) == ZP[3](omega^u)
|
||||
# Allow the last value to be either 0 or 1 for full ZK
|
||||
assert ZP[4](omega^u) in (0, 1)
|
||||
|
||||
y = K.random_element()
|
||||
|
||||
gate_0 = f_1_X * (a_1_X - a_5_X)
|
||||
gate_1 = f_2_X * a_1_X
|
||||
gate_2 = f_3_X * ((1 - a_1_X) * (a_2_X + a_3_X) - a_4_X)
|
||||
gate_3 = f_4_X * (a_1_X * a_2_X * a_3_X - a_4_X)
|
||||
|
||||
c = gate_0 + y * gate_1 + y^2 * gate_2 + y^3 * gate_3
|
||||
t = X^n - 1
|
||||
for i in range(n):
|
||||
assert h(omega^i) == 0
|
||||
# Normally we do:
|
||||
#h = c / t
|
||||
# But for some reason sage is producing fractional coefficients
|
||||
h, rem = c.quo_rem(t)
|
||||
assert rem == 0
|
||||
|
||||
# We send commitments to the terms of h(X)
|
||||
# h_0(x), ..., h_{d - 1}(x)
|
||||
# Commitments:
|
||||
# H = [H_0, ..., H_{d - 1}]
|
||||
|
||||
x = K.random_element()
|
||||
|
||||
# Send evaluations at x of everything we committed to so far
|
||||
# A_0(x), ..., A_{m - 1}(x)
|
||||
# ZP,0(x), ..., ZP,b-1(x)
|
||||
# H_0(x), ..., H_{d-1}(x)
|
||||
a_evals = [a_1_X(x), a_2_X(x), a_3_X(x), a_4_X(x), a_5_X(x)]
|
||||
|
||||
h_evals = []
|
||||
# Iterate starting from lowest powers first
|
||||
h_test = 0
|
||||
for i, h_i in enumerate(h):
|
||||
h_evals.append(h_i * x^i)
|
||||
|
||||
h_test += h_i * X^i
|
||||
assert h_test == h
|
||||
assert sum(h_evals) == h(x)
|
||||
|
||||
assert sum(h_evals) * t(x) == (
|
||||
f_1_X(x) * (a_evals[0] - a_evals[4])
|
||||
+ y * f_2_X(x) * a_evals[0]
|
||||
+ y^2 * f_3_X(x) * ((1 - a_evals[0]) * (a_evals[1] + a_evals[2])
|
||||
- a_evals[3])
|
||||
+ y^3 * f_4_X(x) * (a_evals[0] * a_evals[1] * a_evals[2] - a_evals[3]))
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import random
|
||||
|
||||
def sample_random(fp, seed=None):
|
||||
rnd = random.Random(seed)
|
||||
# Range of the field is 0 ... p - 1
|
||||
return fp(rnd.randint(0, fp.p - 1))
|
||||
|
||||
def is_power_of_two(n):
|
||||
# Power of two number is represented by a single digit
|
||||
# followed by zeroes.
|
||||
return n & (n - 1) == 0
|
||||
|
||||
#| ## Choosing roots of unity
|
||||
def get_omega(fp, n, seed=None):
|
||||
"""
|
||||
Given a field, this method returns an n^th root of unity.
|
||||
If the seed is not None then this method will return the
|
||||
same n'th root of unity for every run with the same seed
|
||||
|
||||
This only makes sense if n is a power of 2.
|
||||
"""
|
||||
assert is_power_of_two(n)
|
||||
# https://crypto.stackexchange.com/questions/63614/finding-the-n-th-root-of-unity-in-a-finite-field
|
||||
while True:
|
||||
# Sample random x != 0
|
||||
x = sample_random(fp, seed)
|
||||
# Compute g = x^{(q - 1)/n}
|
||||
y = pow(x, (fp.p - 1) // n)
|
||||
# If g^{n/2} != 1 then g is a primitive root
|
||||
if y != 1 and pow(y, n // 2) != 1:
|
||||
assert pow(y, n) == 1, "omega must be 2nd root of unity"
|
||||
return y
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
import numpy as np
|
||||
from finite_fields import finitefield
|
||||
|
||||
class Variable:
|
||||
|
||||
def __init__(self, name, fp):
|
||||
self.name = name
|
||||
self.fp = fp
|
||||
|
||||
def __pow__(self, n):
|
||||
expr = MultiplyExpression(self.fp)
|
||||
expr.set_symbol(self.name, n)
|
||||
return expr
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
def termify(self):
|
||||
expr = MultiplyExpression(self.fp)
|
||||
expr.set_symbol(self.name, 1)
|
||||
return expr
|
||||
|
||||
class MultiplyExpression:
|
||||
|
||||
def __init__(self, fp):
|
||||
self.coeff = fp(1)
|
||||
self.symbols = {}
|
||||
self.fp = fp
|
||||
|
||||
def copy(self):
|
||||
result = MultiplyExpression(self.fp)
|
||||
result.coeff = self.coeff
|
||||
result.symbols = self.symbols.copy()
|
||||
return result
|
||||
|
||||
def clean(self):
|
||||
for symbol in list(self.symbols.keys()):
|
||||
if self.symbols[symbol] == 0:
|
||||
del self.symbols[symbol]
|
||||
|
||||
def matches(self, other):
|
||||
return self.symbols == other.symbols
|
||||
|
||||
def set_symbol(self, var_name, power):
|
||||
self.symbols[var_name] = power
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self.coeff == other.coeff and
|
||||
self.symbols == other.symbols)
|
||||
|
||||
def __neg__(self):
|
||||
result = self.copy()
|
||||
result.coeff *= -1
|
||||
return result
|
||||
|
||||
def __mul__(self, expr):
|
||||
result = MultiplyExpression(self.fp)
|
||||
result.coeff = self.coeff
|
||||
result.symbols = self.symbols.copy()
|
||||
|
||||
if isinstance(expr, np.int64) or isinstance(expr, int):
|
||||
expr = self.fp(int(expr))
|
||||
|
||||
if hasattr(expr, "field"):
|
||||
result.coeff *= expr
|
||||
return result
|
||||
|
||||
if isinstance(expr, Variable):
|
||||
expr = expr.termify()
|
||||
|
||||
for var_name, power in expr.symbols.items():
|
||||
if var_name in result.symbols:
|
||||
result.symbols[var_name] += power
|
||||
else:
|
||||
result.symbols[var_name] = power
|
||||
|
||||
# Remember to multiply the coefficients
|
||||
result.coeff *= expr.coeff
|
||||
return result
|
||||
|
||||
def __add__(self, expr):
|
||||
if isinstance(expr, Variable):
|
||||
expr = expr.termify()
|
||||
|
||||
if self.matches(expr):
|
||||
result = self.copy()
|
||||
result.coeff += expr.coeff
|
||||
return result
|
||||
|
||||
return MultivariatePolynomial([self, expr])
|
||||
|
||||
def __sub__(self, expr):
|
||||
expr = -expr
|
||||
return self + expr
|
||||
|
||||
def evaluate(self, symbol_map):
|
||||
result = MultiplyExpression(self.fp)
|
||||
for symbol, power in self.symbols.items():
|
||||
if symbol in symbol_map:
|
||||
value = symbol_map[symbol]
|
||||
result *= value**power
|
||||
else:
|
||||
result *= Variable(symbol, self.fp)**power
|
||||
return result
|
||||
|
||||
def __str__(self):
|
||||
repr = ""
|
||||
first = True
|
||||
if self.coeff != 1:
|
||||
repr += str(self.coeff)
|
||||
first = False
|
||||
for var_name, power in self.symbols.items():
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
repr += " "
|
||||
|
||||
if power == 1:
|
||||
repr += var_name
|
||||
else:
|
||||
repr += var_name + "^" + str(power)
|
||||
|
||||
return repr
|
||||
|
||||
class MultivariatePolynomial:
|
||||
|
||||
def __init__(self, terms=[]):
|
||||
self.terms = terms
|
||||
|
||||
def copy(self):
|
||||
terms = [term.copy() for term in self.terms]
|
||||
return MultivariatePolynomial(terms)
|
||||
|
||||
# Operations can accept Variables and constants
|
||||
# so we make sure to convert them to MultiplyExpression types
|
||||
def _convert_term(self, term):
|
||||
if isinstance(term, Variable):
|
||||
term = term.termify()
|
||||
|
||||
if hasattr(term, "field"):
|
||||
expr = MultiplyExpression(term.field)
|
||||
expr.coeff = term
|
||||
term = expr
|
||||
|
||||
return term
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.terms)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.terms == other.terms
|
||||
|
||||
def __neg__(self):
|
||||
terms = [-term for term in self.terms]
|
||||
return MultivariatePolynomial(terms)
|
||||
|
||||
def __add__(self, term):
|
||||
term = self._convert_term(term)
|
||||
|
||||
if isinstance(term, MultivariatePolynomial):
|
||||
# Recursively apply addition operation
|
||||
result = self.copy()
|
||||
for other_term in term.terms:
|
||||
result += other_term
|
||||
return result
|
||||
|
||||
assert isinstance(term, MultiplyExpression)
|
||||
# Delete ^0 variables
|
||||
term.clean()
|
||||
|
||||
# Skip terms where the coeff is 0
|
||||
if term.coeff == 0:
|
||||
return self
|
||||
|
||||
result = self.copy()
|
||||
result_term = result._find(term)
|
||||
|
||||
if result_term is None:
|
||||
result.terms.append(term)
|
||||
else:
|
||||
result_term.coeff += term.coeff
|
||||
|
||||
return result
|
||||
|
||||
def __sub__(self, term):
|
||||
term = -term
|
||||
return self + term
|
||||
|
||||
def __mul__(self, term):
|
||||
term = self._convert_term(term)
|
||||
|
||||
if isinstance(term, MultivariatePolynomial):
|
||||
# Recursively apply addition operation
|
||||
result = MultivariatePolynomial()
|
||||
for other_term in term.terms:
|
||||
result += self * other_term
|
||||
return result
|
||||
|
||||
assert isinstance(term, MultiplyExpression)
|
||||
# Delete ^0 variables
|
||||
term.clean()
|
||||
|
||||
# Skip terms where the coeff is 0
|
||||
if term.coeff == 0:
|
||||
return self
|
||||
|
||||
terms = [self_term * term for self_term in self.terms]
|
||||
result = MultivariatePolynomial(terms)
|
||||
|
||||
return result
|
||||
|
||||
def divmod(self, poly):
|
||||
assert isinstance(poly, MultivariatePolynomial)
|
||||
# https://www.win.tue.nl/~aeb/2WF02/groebner.pdf
|
||||
|
||||
def _find(self, other):
|
||||
for term in self.terms:
|
||||
if term.matches(other):
|
||||
return term
|
||||
return None
|
||||
|
||||
def evaluate(self, variable_map):
|
||||
p = MultivariatePolynomial()
|
||||
for term in self.terms:
|
||||
assert isinstance(term, MultiplyExpression)
|
||||
p += term.evaluate(variable_map)
|
||||
return p
|
||||
|
||||
def _assert_unique_terms(self):
|
||||
for i, term1 in enumerate(self.terms):
|
||||
for q, term2 in enumerate(self.terms):
|
||||
if i == q:
|
||||
continue
|
||||
assert not term1.matches(term2)
|
||||
|
||||
def filter(self, variables):
|
||||
p = MultivariatePolynomial()
|
||||
for term in self.terms:
|
||||
assert isinstance(term, MultiplyExpression)
|
||||
|
||||
skip = False
|
||||
for variable in variables:
|
||||
symbol = variable.name
|
||||
if symbol in term.symbols:
|
||||
skip = True
|
||||
|
||||
if not skip:
|
||||
p += term
|
||||
return p
|
||||
|
||||
def __str__(self):
|
||||
if not self.terms:
|
||||
return "0"
|
||||
|
||||
repr = ""
|
||||
first = True
|
||||
for term in self.terms:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
repr += " + "
|
||||
repr += str(term)
|
||||
return repr
|
||||
|
||||
if __name__ == "__main__":
|
||||
from finite_fields import finitefield
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
fp = finitefield.IntegersModP(p)
|
||||
|
||||
x = Variable("X")
|
||||
y = Variable("Y")
|
||||
z = Variable("Z")
|
||||
|
||||
print(y**2 + y**2)
|
||||
|
||||
p = x**3 * y**2 * x**2 * fp(5) * fp(2) + x**3 * y + z + fp(6)
|
||||
q = x**3 * y * fp(3) + y
|
||||
print(p)
|
||||
print(q)
|
||||
print(p + q)
|
||||
print(p * q)
|
||||
print(-q)
|
||||
print(p - q)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
from finite_fields import finitefield
|
||||
|
||||
q = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
fq = finitefield.IntegersModP(q)
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
#import numpy as np
|
||||
from groth_poly_commit import Scalar, poly_commit, create_proof, verify_proof
|
||||
|
||||
K = Scalar
|
||||
#R.<x> = LaurentPolynomialRing(K)
|
||||
R.<x> = PolynomialRing(K)
|
||||
|
||||
var_one = K(1)
|
||||
var_x = K(4)
|
||||
var_y = K(6)
|
||||
var_s = K(1)
|
||||
var_xy = var_x * var_y
|
||||
var_x_y = var_x + var_y
|
||||
var_1_neg_s = var_one - var_s
|
||||
var_sxy = var_s * var_xy
|
||||
var_1_neg_s_x_y = var_1_neg_s * var_x_y
|
||||
#var_s_neg_1 = -var_1_neg_s
|
||||
var_zero = K(0)
|
||||
|
||||
public_value = var_s * (var_x * var_y) + (1 - var_s) * (var_x + var_y)
|
||||
|
||||
# x * y = xy
|
||||
a1 = var_x
|
||||
b1 = var_y
|
||||
c1 = var_xy
|
||||
Ql1 = 0
|
||||
Qr1 = 0
|
||||
Qm1 = 1
|
||||
Qo1 = -1
|
||||
Qc1 = 0
|
||||
assert Ql1 * a1 + Qr1 * b1 + Qm1 * a1 * b1 + Qo1 * c1 + Qc1 == 0
|
||||
|
||||
# x + y = (x + y)
|
||||
a2 = var_x
|
||||
b2 = var_y
|
||||
c2 = var_x_y
|
||||
Ql2 = 1
|
||||
Qr2 = 1
|
||||
Qm2 = 0
|
||||
Qo2 = -1
|
||||
Qc2 = 0
|
||||
assert Ql2 * a2 + Qr2 * b2 + Qm2 * a2 * b2 + Qo2 * c2 + Qc2 == 0
|
||||
|
||||
# 1 - s = (1 - s)
|
||||
a3 = var_one
|
||||
b3 = var_s
|
||||
c3 = var_1_neg_s
|
||||
Ql3 = 1
|
||||
Qr3 = -1
|
||||
Qm3 = 0
|
||||
Qo3 = -1
|
||||
Qc3 = 0
|
||||
assert Ql3 * a3 + Qr3 * b3 + Qm3 * a3 * b3 + Qo3 * c3 + Qc3 == 0
|
||||
|
||||
# s * (xy) = sxy
|
||||
a4 = var_s
|
||||
b4 = var_xy
|
||||
c4 = var_sxy
|
||||
Ql4 = 0
|
||||
Qr4 = 0
|
||||
Qm4 = 1
|
||||
Qo4 = -1
|
||||
Qc4 = 0
|
||||
assert Ql4 * a4 + Qr4 * b4 + Qm4 * a4 * b4 + Qo4 * c4 + Qc4 == 0
|
||||
|
||||
# (1 - s) * (x + y) = [(1 - s)(x + y)]
|
||||
a5 = var_1_neg_s
|
||||
b5 = var_x_y
|
||||
c5 = var_1_neg_s_x_y
|
||||
Ql5 = 0
|
||||
Qr5 = 0
|
||||
Qm5 = 1
|
||||
Qo5 = -1
|
||||
Qc5 = 0
|
||||
assert Ql5 * a5 + Qr5 * b5 + Qm5 * a5 * b5 + Qo5 * c5 + Qc5 == 0
|
||||
|
||||
# (sxy) + [(1 - s)(x + y)] = public_value
|
||||
a6 = var_sxy
|
||||
b6 = var_1_neg_s_x_y
|
||||
# Unused
|
||||
c6 = var_zero
|
||||
|
||||
Ql6 = 1
|
||||
Qr6 = 1
|
||||
Qm6 = 0
|
||||
Qo6 = 0
|
||||
Qc6 = -public_value
|
||||
assert Ql6 * a6 + Qr6 * b6 + Qm6 * a6 * b6 + Qo6 * c6 + Qc6 == 0
|
||||
|
||||
# one == 1
|
||||
a7 = var_one
|
||||
# Unused
|
||||
b7 = var_zero
|
||||
# Unused
|
||||
c7 = var_zero
|
||||
|
||||
Ql7 = 1
|
||||
Qr7 = 0
|
||||
Qm7 = 0
|
||||
Qo7 = 0
|
||||
Qc7 = -1
|
||||
assert Ql7 * a7 + Qr7 * b7 + Qm7 * a7 * b7 + Qo7 * c7 + Qc7 == 0
|
||||
|
||||
a = [a1, a2, a3, a4, a5, a6, a7]
|
||||
b = [b1, b2, b3, b4, b5, b6, b7]
|
||||
c = [c1, c2, c3, c4, c5, c6, c7]
|
||||
|
||||
Ql = [Ql1, Ql2, Ql3, Ql4, Ql5, Ql6]
|
||||
Qr = [Qr1, Qr2, Qr3, Qr4, Qr5, Qr6]
|
||||
Qm = [Qm1, Qm2, Qm3, Qm4, Qm5, Qm6]
|
||||
Qo = [Qo1, Qo2, Qo3, Qo4, Qo5, Qo6]
|
||||
Qc = [Qc1, Qc2, Qc3, Qc4, Qc5, Qc6]
|
||||
|
||||
# 0 1 2 3 4 5 6
|
||||
# a: x, x, 1, s, 1 - s, sxy, 1
|
||||
#
|
||||
# 7 8 9 10 11 12 13
|
||||
# b: y, y, s, xy, x + y, (1 - s)(x + y), -
|
||||
#
|
||||
# 14 15 16 17 18 19 20
|
||||
# c: xy, x + y, 1 - s, sxy, (1 - s)(x + y), -, -
|
||||
|
||||
permuted_indices = [
|
||||
1, 0, 6, 9, 16, 17, 2,
|
||||
8, 7, 3, 14, 15, 18, 13,
|
||||
10, 11, 4, 5, 12, 19, 20
|
||||
]
|
||||
eval_domain = range(0, len(permuted_indices))
|
||||
|
||||
witness = a + b + c
|
||||
for i, val in enumerate(a + b + c):
|
||||
assert val == witness[permuted_indices[i]]
|
||||
|
||||
#def lagrange(domain, codomain):
|
||||
# S.<x> = PolynomialRing(K)
|
||||
# p = S.lagrange_polynomial(zip(eval_domain, permuted_indices))
|
||||
# # Convert to a Laurent polynomial
|
||||
# return R(p)
|
||||
|
||||
# This is what the prover passes to the verifier
|
||||
witness_y = R.lagrange_polynomial(enumerate(witness))
|
||||
assert witness_y(12) == witness[12]
|
||||
|
||||
witness_x_a = R.lagrange_polynomial(
|
||||
zip(eval_domain[0:7], eval_domain[0:7]))
|
||||
witness_x_b = R.lagrange_polynomial(
|
||||
zip(eval_domain[7:14], eval_domain[7:14]))
|
||||
witness_x_c = R.lagrange_polynomial(
|
||||
zip(eval_domain[14:], eval_domain[14:]))
|
||||
|
||||
assert witness_x_a(2) == eval_domain[2]
|
||||
assert witness_x_b(8) == eval_domain[8]
|
||||
assert witness_x_c(16) == eval_domain[16]
|
||||
|
||||
witness_x_a_prime = R.lagrange_polynomial(
|
||||
zip(eval_domain[0:7], permuted_indices[0:7]))
|
||||
witness_x_b_prime = R.lagrange_polynomial(
|
||||
zip(eval_domain[7:14], permuted_indices[7:14]))
|
||||
witness_x_c_prime = R.lagrange_polynomial(
|
||||
zip(eval_domain[14:], permuted_indices[14:]))
|
||||
|
||||
assert witness_x_a_prime(2) == permuted_indices[2]
|
||||
assert witness_x_b_prime(8) == permuted_indices[8]
|
||||
assert witness_x_c_prime(16) == permuted_indices[16]
|
||||
|
||||
v1 = K(2)
|
||||
v2 = K(3)
|
||||
px = 1
|
||||
|
||||
for i in range(0, len(a)):
|
||||
px *= v1 + witness_x_a(i) + v2 * witness_y(i)
|
||||
for i in range(len(a), 2 * len(a)):
|
||||
px *= v1 + witness_x_b(i) + v2 * witness_y(i)
|
||||
for i in range(2 * len(a), 3 * len(a)):
|
||||
px *= v1 + witness_x_c(i) + v2 * witness_y(i)
|
||||
|
||||
px_prime = 1
|
||||
|
||||
for i in range(0, len(a)):
|
||||
px_prime *= v1 + witness_x_a_prime(i) + v2 * witness_y(i)
|
||||
for i in range(len(a), 2 * len(a)):
|
||||
px_prime *= v1 + witness_x_b_prime(i) + v2 * witness_y(i)
|
||||
for i in range(2 * len(a), 3 * len(a)):
|
||||
px_prime *= v1 + witness_x_c_prime(i) + v2 * witness_y(i)
|
||||
|
||||
assert px == px_prime
|
||||
|
||||
@@ -1,360 +0,0 @@
|
||||
F101 = Integers(101)
|
||||
E = EllipticCurve(F101, [0, 3])
|
||||
R.<X> = PolynomialRing(F101)
|
||||
# Extension field of points of 101, and solutions of x^2 + 2
|
||||
K.<X> = GF(101**2, modulus=X^2 + 2)
|
||||
# y^2 = x^3 + 3 in this curve defined over the extension field.
|
||||
# Needed for pairing.
|
||||
E2 = EllipticCurve(K, [0, 3])
|
||||
# Generator point because 1^3 + 3 = 4 which is sqrt of 2
|
||||
G = E([1, 2])
|
||||
G2 = E2([36, 31*X])
|
||||
assert G.order() == 17
|
||||
F17 = Integers(17)
|
||||
assert F17.square_roots_of_one() == (1, 16)
|
||||
# 16 == -1
|
||||
# so now we have the 4th roots of 1
|
||||
w = vector(F17, [1, 4, -1, -4])
|
||||
# omega = 4, omega^0 = 1, omega^1 = 4, omega^3 = -1 = 13, omega^3 = 13
|
||||
|
||||
# so now we are still defining our reference string
|
||||
|
||||
# we have 4 x labels for our permutation vector but we need 12
|
||||
# so we generate 2 cosets using quadratic non-residues in F
|
||||
# all 3 cosets should not share any value in common
|
||||
k1 = 2
|
||||
k2 = 3
|
||||
|
||||
assert w == vector(F17, [1, 4, 16, 13])
|
||||
assert k1 * w == vector(F17, [2, 8, 15, 9])
|
||||
assert k2 * w == vector(F17, [3, 12, 14, 5])
|
||||
|
||||
A = matrix(F17, [
|
||||
[1, 1, 1, 1],
|
||||
[4^0, 4^1, 4^2, 4^3],
|
||||
[16^0, 16^1, 16^2, 16^3],
|
||||
[13^0, 13^1, 13^2, 13^3]
|
||||
])
|
||||
Ai = A.inverse()
|
||||
P.<x> = F17[]
|
||||
x = P.0
|
||||
|
||||
# We only have 3 gates in this example for x^3 + x = 30
|
||||
|
||||
# x x^2 x^3
|
||||
# x x x
|
||||
# x^2 x^3 0
|
||||
|
||||
# public input: 30
|
||||
|
||||
# we have 4 w values so the last column is empty (all set to 0 in this case)
|
||||
|
||||
fa = P.lagrange_polynomial(zip([1, 4, 16, 13], [3, 9, 27, 0]))
|
||||
#fa = P(list(Ai * vector(F17, [3, 9, 27, 0])))
|
||||
assert fa(1) == 3
|
||||
assert fa(4) == 9
|
||||
assert fa(16) == 27
|
||||
assert fa(13) == 0
|
||||
fb = P(list(Ai * vector(F17, [3, 3, 3, 0])))
|
||||
assert fb(1) == 3
|
||||
assert fb(4) == 3
|
||||
assert fb(16) == 3
|
||||
assert fb(13) == 0
|
||||
fc = P(list(Ai * vector(F17, [9, 27, 0, 0])))
|
||||
assert fc(1) == 9
|
||||
assert fc(4) == 27
|
||||
assert fc(16) == 0
|
||||
assert fc(13) == 0
|
||||
|
||||
# List of operations
|
||||
#
|
||||
# mul, mul, add/cons, null
|
||||
|
||||
ql = P(list(Ai * vector(F17, [0, 0, 1, 0])))
|
||||
qr = P(list(Ai * vector(F17, [0, 0, 1, 0])))
|
||||
qm = P(list(Ai * vector(F17, [1, 1, 0, 0])))
|
||||
qo = P(list(Ai * vector(F17, [-1, -1, 0, 0])))
|
||||
qc = P(list(Ai * vector(F17, [0, 0, -30, 0])))
|
||||
|
||||
# permutation/copy constraints
|
||||
|
||||
# We are using the coset values here for a, b, c
|
||||
|
||||
# 1 4 16 13
|
||||
# 2 8 15 9
|
||||
# 3 12 14 5
|
||||
|
||||
# Applying the permutation for:
|
||||
|
||||
# x x^2 x^3
|
||||
# x x x
|
||||
# x^2 x^3 0
|
||||
|
||||
# then we get:
|
||||
|
||||
# 2 3 12 13
|
||||
# 1 15 8 9
|
||||
# 4 16 14 5
|
||||
|
||||
# We swap indices whenever there is an equality between wires:
|
||||
|
||||
# a1 = b1
|
||||
# a2 = c1
|
||||
# ...
|
||||
|
||||
sa = P(list(Ai * vector(F17, [2, 3, 12, 13])))
|
||||
sb = P(list(Ai * vector(F17, [1, 15, 8, 9])))
|
||||
sc = P(list(Ai * vector(F17, [4, 16, 14, 5])))
|
||||
|
||||
# Setup phase complete
|
||||
|
||||
# Prove phase
|
||||
|
||||
# Round 1
|
||||
|
||||
# Create vanishing polynomial which is zero for every root of unity.
|
||||
# That is Z(w_1) = Z(w_2) = ... = 0
|
||||
Z = x^4 - 1
|
||||
assert Z(1) == 0
|
||||
assert Z(4) == 0
|
||||
assert Z(16) == 0
|
||||
assert Z(13) == 0
|
||||
|
||||
# 9 random blinding values. We will use:
|
||||
# 7, 4, 11, 12, 16, 2
|
||||
# 14, 11, 7 (used in round 2)
|
||||
|
||||
# Blind our witness polynomials
|
||||
# The blinding factors will disappear at the evaluation points.
|
||||
a = (7*x + 4) * Z + fa
|
||||
b = (11*x + 12) * Z + fb
|
||||
c = (16*x + 2) * Z + fc
|
||||
|
||||
# During the SRS phase we created a random s point and its powers
|
||||
s = 2
|
||||
# So now we evaluate a, b, c with these powers of G
|
||||
a_s = ZZ(a(s)) * G
|
||||
b_s = ZZ(b(s)) * G
|
||||
c_s = ZZ(c(s)) * G
|
||||
|
||||
# Round 2
|
||||
|
||||
# Random transcript challenges
|
||||
beta = 12
|
||||
gamma = 13
|
||||
# Build accumulation
|
||||
acc = 1
|
||||
accs = []
|
||||
for i in range(4):
|
||||
# w_{n + j} corresponds to b(w[i])
|
||||
# and w_{2n + j} is c(w[i])
|
||||
accs.append(acc)
|
||||
acc = acc * (
|
||||
(a(w[i]) + beta * w[i] + gamma)
|
||||
* (b(w[i]) + beta * k1 * w[i] + gamma)
|
||||
* (c(w[i]) + beta * k2 * w[i] + gamma) /
|
||||
(
|
||||
(a(w[i]) + beta * sa(w[i]) + gamma)
|
||||
* (b(w[i]) + beta * sb(w[i]) + gamma)
|
||||
* (c(w[i]) + beta * sc(w[i]) + gamma)
|
||||
))
|
||||
assert accs == [1, 12, 10, 1]
|
||||
del accs
|
||||
acc = P(list(Ai * vector(F17, [1, 12, 10, 1])))
|
||||
|
||||
Zx = (14*x^2 + 11*x + 7) * Z + acc
|
||||
# Evaluate z(x) at our secret point
|
||||
Z_s = ZZ(Zx(s)) * G
|
||||
|
||||
# Round 3
|
||||
|
||||
alpha = 15
|
||||
|
||||
t1Z = a * b * qm + a * ql + b * qr + c * qo + qc
|
||||
|
||||
t2Z = ((a + beta * x + gamma)
|
||||
* (b + beta * k1 * x + gamma)
|
||||
* (c + beta * k2 * x + gamma)) * Zx * alpha
|
||||
|
||||
# w[1] is our first root of unity
|
||||
Zw = Zx(w[1] * x)
|
||||
t3Z = -((a + beta * sa + gamma)
|
||||
* (b + beta * sb + gamma)
|
||||
* (c + beta * sc + gamma)) * Zw * alpha
|
||||
|
||||
# Lagrangian polynomial which evaluates to 1 at 1
|
||||
# L_1(w_1) = 1 and 0 on the other evaluation points
|
||||
L = P(list(Ai * vector(F17, [1, 0, 0, 0])))
|
||||
assert L(1) == 1
|
||||
# w_2 = 4
|
||||
assert L(4) == 0
|
||||
|
||||
t4Z = (Zx - 1) * L * alpha^2
|
||||
|
||||
tZ = t1Z + t2Z + t3Z + t4Z
|
||||
# and cancel out the factor Z now
|
||||
t = P(tZ / Z)
|
||||
|
||||
# Split t into 3 parts
|
||||
# t(X) = t_lo(X) + X^n t_mid(X) + X^{2n} t_hi(X)
|
||||
t_list = t.list()
|
||||
t_lo = t_list[0:6]
|
||||
t_mid = t_list[6:12]
|
||||
t_hi = t_list[12:18]
|
||||
# and create the evaluations
|
||||
t_lo_s = ZZ(P(t_lo)(s)) * G
|
||||
t_mid_s = ZZ(P(t_mid)(s)) * G
|
||||
t_hi_s = ZZ(P(t_hi)(s)) * G
|
||||
|
||||
# Round 4
|
||||
|
||||
zeta = 5
|
||||
|
||||
a_ = a(zeta)
|
||||
b_ = b(zeta)
|
||||
c_ = c(zeta)
|
||||
sa_ = sa(zeta)
|
||||
sb_ = sb(zeta)
|
||||
t_ = t(zeta)
|
||||
zw_ = Zx(zeta * w[1])
|
||||
l_ = L(zeta)
|
||||
assert a_ == 8
|
||||
assert b_ == 12
|
||||
assert c_ == 10
|
||||
assert sa_ == 0
|
||||
assert sb_ == 16
|
||||
assert t_ == 3
|
||||
assert zw_ == 14
|
||||
|
||||
r1 = a_ * b_ * qm + a_ * ql + b_ * qr + c_ * qo + qc
|
||||
|
||||
r2 = ((a_ + beta * zeta + gamma)
|
||||
* (b_ + beta * k1 * zeta + gamma)
|
||||
* (c_ + beta * k2 * zeta + gamma)) * Zx * alpha
|
||||
|
||||
r3 = -((a_ + beta * sa_ + gamma)
|
||||
* (b_ + beta * sb_ + gamma)
|
||||
* beta * zw_ * sc * alpha)
|
||||
|
||||
r4 = Zx * l_ * alpha^2
|
||||
|
||||
r = r1 + r2 + r3 + r4
|
||||
|
||||
r_ = r(zeta)
|
||||
assert r_ == 7
|
||||
|
||||
# Round 5
|
||||
|
||||
vega = 12
|
||||
|
||||
v1 = P(t_lo)
|
||||
# Polynomial was in parts consisting of 6 powers
|
||||
v2 = zeta^6 * P(t_mid)
|
||||
v3 = zeta^12 * P(t_hi)
|
||||
v4 = -t_
|
||||
assert v4 == 14
|
||||
|
||||
v5 = (
|
||||
vega * (r - r_)
|
||||
+ vega^2 * (a - a_) + vega^3 * (b - b_) + vega^4 * (c - c_)
|
||||
+ vega^5 * (sa - sa_) + vega^6 * (sb - sb_)
|
||||
)
|
||||
|
||||
W = v1 + v2 + v3 + v4 + v5
|
||||
Wz = W / (x - zeta)
|
||||
# Calculate the opening proof
|
||||
Wzw = (Zx - zw_) / (x - zeta * w[1])
|
||||
|
||||
# Compute evaluations of Wz and Wzw
|
||||
Wz_s = ZZ(Wz(s)) * G
|
||||
Wzw_s = ZZ(Wzw(s)) * G
|
||||
|
||||
# Finished the proving algo
|
||||
proof = (a_s, b_s, c_s, Z_s, t_lo_s, t_mid_s, t_hi_s, Wz_s, Wzw_s,
|
||||
a_, b_, c_, sa_, sb_, r_, zw_)
|
||||
|
||||
# Verification
|
||||
|
||||
qm_s = ZZ(qm(s)) * G
|
||||
ql_s = ZZ(ql(s)) * G
|
||||
qr_s = ZZ(qr(s)) * G
|
||||
qo_s = ZZ(qo(s)) * G
|
||||
qc_s = ZZ(qc(s)) * G
|
||||
sa_s = ZZ(sa(s)) * G
|
||||
sb_s = ZZ(sb(s)) * G
|
||||
sc_s = ZZ(sc(s)) * G
|
||||
|
||||
# Check all the points are on the curve.
|
||||
# y^2 = x^3 + 3
|
||||
# ...
|
||||
|
||||
# Also check the scalar values are in the group for F17
|
||||
# ...
|
||||
|
||||
# step 4: random upsilon
|
||||
upsilon = 4
|
||||
|
||||
# step 5
|
||||
Z_z = F17(zeta^4 - 1)
|
||||
assert Z_z == 12
|
||||
|
||||
# step 6
|
||||
# Calculate evaluation of L1 at zeta
|
||||
L1_z = F17((zeta^4 - 1) / (4 * (zeta - 1)))
|
||||
assert L1_z == 5
|
||||
|
||||
# step 7
|
||||
# no public inputs in this example
|
||||
|
||||
# step 8
|
||||
t_ = (r_ - (a_ + beta * sa_ + gamma)
|
||||
* (b_ + beta * sb_ + gamma)
|
||||
* (c_ + gamma) * zw_ * alpha
|
||||
- L1_z * alpha^2) / Z_z
|
||||
assert t_ == 3
|
||||
|
||||
# step 9
|
||||
# qx_s are points, and we are multiplying them by scalars
|
||||
# so convert the values to integers first
|
||||
d1 = (ZZ(a_ * b_ * vega) * qm_s
|
||||
+ ZZ(a_ * vega) * ql_s
|
||||
+ ZZ(b_ * vega) * qr_s
|
||||
+ ZZ(c_ * vega) * qo_s
|
||||
+ vega * qc_s)
|
||||
d2 = ZZ((a_ + beta * zeta + gamma)
|
||||
* (b_ + beta * k1 * zeta + gamma)
|
||||
* (c_ + beta * k2 * zeta + gamma)
|
||||
* alpha * vega
|
||||
+ L1_z * alpha^2 * vega
|
||||
+ F17(upsilon)) * Z_s
|
||||
d3 = -ZZ((a_ + beta * sa_ + gamma)
|
||||
* (b_ + beta * sb_ + gamma)
|
||||
* alpha * vega * beta * zw_) * sc_s
|
||||
d = d1 + d2 + d3
|
||||
|
||||
# step 10
|
||||
f = (t_lo_s + zeta^6 * t_mid_s + zeta^12 * t_hi_s
|
||||
+ d
|
||||
+ vega^2 * a_s + vega^3 * b_s + vega^4 * c_s
|
||||
+ vega^5 * sa_s + vega^6 * sb_s)
|
||||
|
||||
# step 11
|
||||
e = ZZ(t_ + vega * r_
|
||||
+ vega^2 * a_ + vega^3 * b_ + vega^4 * c_
|
||||
+ vega^5 * sa_ + vega^6 * sb_
|
||||
+ upsilon * zw_) * G
|
||||
|
||||
# step 12
|
||||
# construct points for the pairing check
|
||||
x1 = Wz_s + upsilon * Wzw_s
|
||||
x2 = s * G2
|
||||
|
||||
y1 = zeta * Wz_s + ZZ(upsilon * zeta * w[1]) * Wzw_s + f - e
|
||||
y2 = G2
|
||||
|
||||
# do the pairing check
|
||||
x1_ = E2(x1)
|
||||
x2_ = E2(x2)
|
||||
y1_ = E2(y1)
|
||||
y2_ = E2(y2)
|
||||
assert x1_.weil_pairing(x2_, 17) == y1_.weil_pairing(y2_, 17)
|
||||
@@ -1,325 +0,0 @@
|
||||
q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
|
||||
K = GF(q)
|
||||
P.<X> = K[]
|
||||
|
||||
# The pallas and vesta curves are 2-adic. This means there is a large
|
||||
# power of 2 subgroup within both of their fields.
|
||||
# This function finds a generator for this subgroup within the field.
|
||||
def get_omega():
|
||||
# Slower alternative:
|
||||
# generator = K.multiplicative_generator()
|
||||
# Just hardcode the value here instead
|
||||
generator = K(5)
|
||||
assert (q - 1) % 2^32 == 0
|
||||
# Root of unity
|
||||
t = (q - 1) / 2^32
|
||||
omega = generator**t
|
||||
|
||||
assert omega != 1
|
||||
assert omega^(2^16) != 1
|
||||
assert omega^(2^31) != 1
|
||||
assert omega^(2^32) == 1
|
||||
|
||||
return omega
|
||||
|
||||
# Order of this element is 2^32
|
||||
omega = get_omega()
|
||||
|
||||
# f(s, x, y) = sxy + (1 - s)(x + y)
|
||||
var_one = K(1)
|
||||
var_x = K(4)
|
||||
var_y = K(6)
|
||||
var_s = K(1)
|
||||
var_xy = var_x * var_y
|
||||
var_x_y = var_x + var_y
|
||||
var_1_neg_s = var_one - var_s
|
||||
var_sxy = var_s * var_xy
|
||||
var_1_neg_s_x_y = var_1_neg_s * var_x_y
|
||||
#var_s_neg_1 = -var_1_neg_s
|
||||
var_zero = K(0)
|
||||
|
||||
public_value = -(var_s * (var_x * var_y) + (1 - var_s) * (var_x + var_y))
|
||||
|
||||
# Ql a + Qr b + Qm a b + Qo c + Qc + P == 0
|
||||
|
||||
# See also the file plonk-naive.sage
|
||||
# x * y = xy
|
||||
a1, b1, c1 = var_x, var_y, var_xy
|
||||
Ql1, Qr1, Qm1, Qo1, Qc1 = 0, 0, 1, -1, 0
|
||||
assert Ql1 * a1 + Qr1 * b1 + Qm1 * a1 * b1 + Qo1 * c1 + Qc1 == 0
|
||||
# x + y = (x + y)
|
||||
a2, b2, c2 = var_x, var_y, var_x_y
|
||||
Ql2, Qr2, Qm2, Qo2, Qc2 = 1, 1, 0, -1, 0
|
||||
assert Ql2 * a2 + Qr2 * b2 + Qm2 * a2 * b2 + Qo2 * c2 + Qc2 == 0
|
||||
# 1 - s = (1 - s)
|
||||
a3, b3, c3 = var_one, var_s, var_1_neg_s
|
||||
Ql3, Qr3, Qm3, Qo3, Qc3 = 1, -1, 0, -1, 0
|
||||
assert Ql3 * a3 + Qr3 * b3 + Qm3 * a3 * b3 + Qo3 * c3 + Qc3 == 0
|
||||
# s * (xy) = sxy
|
||||
a4, b4, c4 = var_s, var_xy, var_sxy
|
||||
Ql4, Qr4, Qm4, Qo4, Qc4 = 0, 0, 1, -1, 0
|
||||
assert Ql4 * a4 + Qr4 * b4 + Qm4 * a4 * b4 + Qo4 * c4 + Qc4 == 0
|
||||
# (1 - s) * (x + y) = [(1 - s)(x + y)]
|
||||
a5, b5, c5 = var_1_neg_s, var_x_y, var_1_neg_s_x_y
|
||||
Ql5, Qr5, Qm5, Qo5, Qc5 = 0, 0, 1, -1, 0
|
||||
assert Ql5 * a5 + Qr5 * b5 + Qm5 * a5 * b5 + Qo5 * c5 + Qc5 == 0
|
||||
# (sxy) + [(1 - s)(x + y)] = public_value
|
||||
# c6 is unused
|
||||
a6, b6, c6 = var_sxy, var_1_neg_s_x_y, var_zero
|
||||
Ql6, Qr6, Qm6, Qo6, Qc6 = 1, 1, 0, 0, 0
|
||||
assert Ql6 * a6 + Qr6 * b6 + Qm6 * a6 * b6 + Qo6 * c6 + Qc6 + public_value == 0
|
||||
# one == 1, b7 and c7 unused
|
||||
a7, b7, c7 = var_one, var_zero, var_zero
|
||||
Ql7, Qr7, Qm7, Qo7, Qc7 = 1, 0, 0, 0, -1
|
||||
assert Ql7 * a7 + Qr7 * b7 + Qm7 * a7 * b7 + Qo7 * c7 + Qc7 == 0
|
||||
# Add a last fake constraint so n is a power of 2
|
||||
# This is needed since we are working with omega whose size is 2^32
|
||||
# and we will create a generator from it whose order is 2^3
|
||||
a8, b8, c8 = var_zero, var_zero, var_zero
|
||||
Ql8, Qr8, Qm8, Qo8, Qc8 = 0, 0, 0, 0, 0
|
||||
assert Ql8 * a8 + Qr8 * b8 + Qm8 * a8 * b8 + Qo8 * c8 + Qc8 == 0
|
||||
|
||||
a = [a1, a2, a3, a4, a5, a6, a7, a8]
|
||||
b = [b1, b2, b3, b4, b5, b6, b7, b8]
|
||||
c = [c1, c2, c3, c4, c5, c6, c7, c8]
|
||||
|
||||
Ql = [Ql1, Ql2, Ql3, Ql4, Ql5, Ql6, Ql7, Ql8]
|
||||
Qr = [Qr1, Qr2, Qr3, Qr4, Qr5, Qr6, Qr7, Qr8]
|
||||
Qm = [Qm1, Qm2, Qm3, Qm4, Qm5, Qm6, Qm7, Qm8]
|
||||
Qo = [Qo1, Qo2, Qo3, Qo4, Qo5, Qo6, Qo7, Qo8]
|
||||
Qc = [Qc1, Qc2, Qc3, Qc4, Qc5, Qc6, Qc7, Qc8]
|
||||
|
||||
public_values = [0, 0, 0, 0, 0, public_value, 0, 0]
|
||||
|
||||
n = 8
|
||||
|
||||
for a_i, b_i, c_i, Ql_i, Qr_i, Qm_i, Qo_i, Qc_i, public_i in \
|
||||
zip(a, b, c, Ql, Qr, Qm, Qo, Qc, public_values):
|
||||
assert (Ql_i * a_i + Qr_i * b_i + Qm_i * a_i * b_i + Qo_i * c_i
|
||||
+ Qc_i + public_i) == 0
|
||||
|
||||
# 0 1 2 3 4 5 6 7
|
||||
# a: x, x, 1, s, 1 - s, sxy, 1 -
|
||||
#
|
||||
# 8 9 10 11 12 13 14 15
|
||||
# b: y, y, s, xy, x + y, (1 - s)(x + y), - -
|
||||
#
|
||||
# 16 17 18 19 20 21 22 23
|
||||
# c: xy, x + y, 1 - s, sxy, (1 - s)(x + y), -, - -
|
||||
|
||||
permuted_indices_a = [1, 0, 6, 10, 18, 19, 2, 7]
|
||||
permuted_indices_b = [8, 9, 3, 16, 17, 20, 14, 15]
|
||||
permuted_indices_c = [11, 12, 4, 5, 13, 21, 22, 23]
|
||||
eval_domain = range(0, n * 3)
|
||||
|
||||
witness = a + b + c
|
||||
permuted_indices = permuted_indices_a + permuted_indices_b + permuted_indices_c
|
||||
for i, val in enumerate(a + b + c):
|
||||
assert val == witness[permuted_indices[i]]
|
||||
|
||||
omega = omega^(2^32 / n)
|
||||
assert omega^n == 1
|
||||
|
||||
# Calculate the vanishing polynomial
|
||||
# This is the same as (X - omega^0)(X - omega^1)...(X - omega^{n - 1})
|
||||
Z_H = X^n - 1
|
||||
assert Z_H(1) == 0
|
||||
assert Z_H(omega^4) == 0
|
||||
|
||||
qL_X = P.lagrange_polynomial((omega^i, Ql_i) for i, Ql_i in enumerate(Ql))
|
||||
qR_X = P.lagrange_polynomial((omega^i, Qr_i) for i, Qr_i in enumerate(Qr))
|
||||
qM_X = P.lagrange_polynomial((omega^i, Qm_i) for i, Qm_i in enumerate(Qm))
|
||||
qO_X = P.lagrange_polynomial((omega^i, Qo_i) for i, Qo_i in enumerate(Qo))
|
||||
qC_X = P.lagrange_polynomial((omega^i, Qc_i) for i, Qc_i in enumerate(Qc))
|
||||
|
||||
PI_X = P.lagrange_polynomial((omega^i, public_i) for i, public_i
|
||||
in enumerate(public_values))
|
||||
|
||||
b_1 = K.random_element()
|
||||
b_2 = K.random_element()
|
||||
b_3 = K.random_element()
|
||||
b_4 = K.random_element()
|
||||
b_5 = K.random_element()
|
||||
b_6 = K.random_element()
|
||||
b_7 = K.random_element()
|
||||
b_8 = K.random_element()
|
||||
b_9 = K.random_element()
|
||||
|
||||
# Round 1
|
||||
|
||||
# Calculate wire witness polynomials
|
||||
a_X = (b_1 * X + b_2) * Z_H + \
|
||||
P.lagrange_polynomial((omega^i, a_i) for i, a_i in enumerate(a))
|
||||
assert a_X(omega^2) == a[2]
|
||||
b_X = (b_3 * X + b_4) * Z_H + \
|
||||
P.lagrange_polynomial((omega^i, b_i) for i, b_i in enumerate(b))
|
||||
assert b_X(omega^5) == b[5]
|
||||
c_X = (b_5 * X + b_6) * Z_H + \
|
||||
P.lagrange_polynomial((omega^i, c_i) for i, c_i in enumerate(c))
|
||||
assert c_X(omega^0) == c[0]
|
||||
|
||||
# Commit to a(X), b(X), c(X)
|
||||
|
||||
# ...
|
||||
|
||||
# Round 2
|
||||
|
||||
beta = K.random_element()
|
||||
gamma = K.random_element()
|
||||
|
||||
def find_quadratic_non_residue():
|
||||
k = K.random_element()
|
||||
while kronecker(k, q) != -1:
|
||||
k = K.random_element()
|
||||
return k
|
||||
|
||||
# These values do not have a square root
|
||||
k1 = find_quadratic_non_residue()
|
||||
k2 = find_quadratic_non_residue()
|
||||
assert k1 != k2
|
||||
|
||||
indices = ([omega^i for i in range(n)]
|
||||
+ [k1 * omega^i for i in range(n)]
|
||||
+ [k2 * omega^i for i in range(n)])
|
||||
# Permuted indices
|
||||
sigma_star = [indices[i] for i in permuted_indices]
|
||||
|
||||
permutation_points = [(1, 1)]
|
||||
for i in range(n - 1):
|
||||
x = omega^(i + 1)
|
||||
y = 1
|
||||
for j in range(i + 1):
|
||||
y *= witness[j] + beta * omega^j + gamma
|
||||
y *= witness[n + j] + beta * k1 * omega^j + gamma
|
||||
y *= witness[2 * n + j] + beta * k2 * omega^j + gamma
|
||||
y /= witness[j] + sigma_star[j] * beta + gamma
|
||||
y /= witness[n + j] + sigma_star[n + j] * beta + gamma
|
||||
y /= witness[2 * n + j] + sigma_star[2 * n + j] * beta + gamma
|
||||
permutation_points.append((x, y))
|
||||
|
||||
z_X = (b_7 * X^2 + b_8 * X + b_9) * Z_H + \
|
||||
P.lagrange_polynomial(permutation_points)
|
||||
|
||||
assert witness[0] == 4
|
||||
assert witness[n] == 6
|
||||
assert witness[2 * n] == var_xy == 24
|
||||
assert sigma_star[0] == omega
|
||||
assert sigma_star[n] == k1 * omega^8
|
||||
assert sigma_star[2 * n] == k1 * omega^11
|
||||
assert z_X(omega^0) == 1
|
||||
assert ((4 + beta + gamma) * (6 + beta * k1 + gamma) * (24 + beta * k2 + gamma)
|
||||
) == (z_X(omega)
|
||||
* (4 + omega * beta + gamma)
|
||||
* (6 + k1 * omega^8 * beta + gamma)
|
||||
* (24 + k1 * omega^11 * beta + gamma))
|
||||
|
||||
assert witness[2] == var_one == 1
|
||||
assert witness[n + 2] == var_s == 1
|
||||
assert witness[2 * n + 2] == var_1_neg_s == 0
|
||||
assert sigma_star[2] == omega^6
|
||||
assert sigma_star[n + 2] == omega^3
|
||||
assert sigma_star[2 * n + 2] == omega^4
|
||||
assert (z_X(omega^2) * (1 + beta * omega^2 + gamma)
|
||||
* (1 + beta * k1 * omega^2 + gamma)
|
||||
* (0 + beta * k2 * omega^2 + gamma)
|
||||
) == (z_X(omega^3) * (1 + omega^6 * beta + gamma)
|
||||
* (1 + omega^3 * beta + gamma)
|
||||
* (0 + omega^4 * beta + gamma))
|
||||
|
||||
|
||||
# Round 3
|
||||
|
||||
alpha = K.random_element()
|
||||
|
||||
Ssigma_1 = P.lagrange_polynomial((omega^i, sigma_star[i]) for i in range(8))
|
||||
Ssigma_2 = P.lagrange_polynomial((omega^i, sigma_star[n + i]) for i in range(8))
|
||||
Ssigma_3 = P.lagrange_polynomial((omega^i, sigma_star[2 * n + i])
|
||||
for i in range(8))
|
||||
assert Ssigma_1(omega^0) == omega^1
|
||||
assert Ssigma_1(omega^3) == k1 * omega^10
|
||||
assert Ssigma_2(omega^2) == omega^3
|
||||
assert Ssigma_3(omega^7) == k2 * omega^7 == k2 * omega^23
|
||||
|
||||
t_X_constraints = ((a_X * b_X * qM_X) + (a_X * qL_X) + (b_X * qR_X)
|
||||
+ (c_X * qO_X) + qC_X + PI_X)
|
||||
for i in range(8):
|
||||
assert t_X_constraints(omega^i) == 0
|
||||
|
||||
t_X_permutations = ((a_X + beta * X + gamma)
|
||||
* (b_X + beta * k1 * X + gamma)
|
||||
* (c_X + beta * k2 * X + gamma) * z_X
|
||||
# Permutated accumulator
|
||||
- (a_X + beta * Ssigma_1 + gamma)
|
||||
* (b_X + beta * Ssigma_2 + gamma)
|
||||
* (c_X + beta * Ssigma_3 + gamma) * z_X(X * omega))
|
||||
for i in range(8):
|
||||
assert t_X_permutations(omega^i) == 0
|
||||
|
||||
L1_X = P.lagrange_polynomial([(1, 1)] + [(omega^i, 0) for i in range(1, n)])
|
||||
assert L1_X(omega^0) == 1
|
||||
assert L1_X(omega^2) == 0
|
||||
t_X_zloops = (z_X - 1) * L1_X
|
||||
assert t_X_zloops(omega^0) == 0
|
||||
assert t_X_zloops(omega^2) == 0
|
||||
assert t_X_zloops(omega^8) == 0
|
||||
|
||||
t = (t_X_constraints + t_X_permutations * alpha + t_X_zloops * alpha^2) / Z_H
|
||||
|
||||
# Commit to t
|
||||
|
||||
# ...
|
||||
|
||||
# Round 4
|
||||
|
||||
zeta = K.random_element()
|
||||
|
||||
a_bar = a_X(zeta)
|
||||
b_bar = b_X(zeta)
|
||||
c_bar = c_X(zeta)
|
||||
s_bar_1 = Ssigma_1(zeta)
|
||||
s_bar_2 = Ssigma_2(zeta)
|
||||
z_bar_omega = z_X(zeta * omega)
|
||||
|
||||
# Now we provide proofs that all the above values are correct openings
|
||||
# of the committed polynomials.
|
||||
|
||||
# And we prove that a reconstructed version of t(X) from the polynomial
|
||||
# commitments of the witness and permutation polynomials equals the
|
||||
# t(X) commitment.
|
||||
# t(X) - r(X) = 0 where r(X) is the reconstructed polynomial.
|
||||
|
||||
# In order to avoid sending Ssigma_1(zeta) and z(zeta), plonk does an
|
||||
# optimization using the Maller trick documented in section 4 under
|
||||
# the title "Reducing the number of field elements"
|
||||
|
||||
# Round 5
|
||||
|
||||
# To reduce the proof by two elements, we construct a linearization polynomial
|
||||
# which only contains 1 interminate per multiplication expression which is
|
||||
# enough to prove the polynomial correctly evaluates.
|
||||
|
||||
r = (
|
||||
# This is proving the constraint polynomial has roots at H
|
||||
(a_bar * b_bar * qM_X) + (a_bar * qL_X) + (b_bar * qR_X)
|
||||
+ (c_bar * qO_X) + PI_X + qC_X
|
||||
|
||||
+ alpha * ((a_bar + beta * zeta + gamma)
|
||||
* (b_bar + beta * k1 * zeta + gamma)
|
||||
* (c_bar + beta * k2 * zeta + gamma) * z_X
|
||||
-
|
||||
(a_bar + beta * s_bar_1 + gamma)
|
||||
* (b_bar + beta * s_bar_2 + gamma)
|
||||
* (c_bar + beta * Ssigma_3 + gamma) * z_bar_omega)
|
||||
|
||||
+ alpha^2 * (z_X - 1) * L1_X(zeta)
|
||||
|
||||
# t = (t_X_constraints + t_X_permutations * alpha + t_X_zloops * alpha^2)
|
||||
# -------------------------------------------------------------------
|
||||
# Z_H
|
||||
- Z_H(zeta) * t
|
||||
)
|
||||
|
||||
assert r(zeta) == 0
|
||||
|
||||
# That is basically the plonk prover. The remaining stuff are details such as
|
||||
# which polynomial commitment scheme you use (kate, bulletproofs, ...)
|
||||
@@ -1,301 +0,0 @@
|
||||
#| # Evaluation Representation of Polynomials and FFT optimizations
|
||||
#| In addition to the coefficient-based representation of polynomials used
|
||||
#| in babysnark.py, for performance we will also use an alternative
|
||||
#| representation where the polynomial is evaluated at a fixed set of points.
|
||||
#| Some operations, like multiplication and division, are significantly more
|
||||
#| efficient in this form.
|
||||
#| We can use FFT-based tools for efficiently converting
|
||||
#| between coefficient and evaluation representation.
|
||||
#|
|
||||
#| This library provides:
|
||||
#| - Fast fourier transform for finite fields
|
||||
#| - Interpolation and evaluation using FFT
|
||||
|
||||
from finite_fields.finitefield import FiniteField
|
||||
from finite_fields.polynomial import polynomialsOver
|
||||
from finite_fields.euclidean import extendedEuclideanAlgorithm
|
||||
import random
|
||||
from finite_fields.numbertype import typecheck, memoize, DomainElement
|
||||
from functools import reduce
|
||||
import numpy as np
|
||||
|
||||
#| ## Fast Fourier Transform on Finite Fields
|
||||
def fft_helper(a, omega, field):
|
||||
"""
|
||||
Given coefficients A of polynomial this method does FFT and returns
|
||||
the evaluation of the polynomial at [omega^0, omega^(n-1)]
|
||||
|
||||
If the polynomial is a0*x^0 + a1*x^1 + ... + an*x^n then the coefficients
|
||||
list is of the form [a0, a1, ... , an].
|
||||
"""
|
||||
n = len(a)
|
||||
assert not (n & (n - 1)), "n must be a power of 2"
|
||||
|
||||
if n == 1:
|
||||
return a
|
||||
|
||||
b, c = a[0::2], a[1::2]
|
||||
b_bar = fft_helper(b, pow(omega, 2), field)
|
||||
c_bar = fft_helper(c, pow(omega, 2), field)
|
||||
a_bar = [field(1)] * (n)
|
||||
for j in range(n):
|
||||
k = j % (n // 2)
|
||||
a_bar[j] = b_bar[k] + pow(omega, j) * c_bar[k]
|
||||
return a_bar
|
||||
|
||||
|
||||
#| ## Representing a polynomial by evaluation at fixed points
|
||||
@memoize
|
||||
def make_polynomial_evalrep(field, omega, n):
|
||||
assert n & n - 1 == 0, "n must be a power of 2"
|
||||
|
||||
# Check that omega is an n'th primitive root of unity
|
||||
assert type(omega) is field
|
||||
omega = field(omega)
|
||||
assert omega**(n) == 1
|
||||
_powers = [omega**i for i in range(n)]
|
||||
assert len(set(_powers)) == n
|
||||
|
||||
_poly_coeff = polynomialsOver(field)
|
||||
|
||||
class PolynomialEvalRep(object):
|
||||
|
||||
def __init__(self, xs, ys):
|
||||
# Each element of xs must be a power of omega.
|
||||
# There must be a corresponding y for every x.
|
||||
if type(xs) is not tuple:
|
||||
xs = tuple(xs)
|
||||
if type(ys) is not tuple:
|
||||
ys = tuple(ys)
|
||||
|
||||
assert len(xs) <= n+1
|
||||
assert len(xs) == len(ys)
|
||||
for x in xs:
|
||||
assert x in _powers
|
||||
for y in ys:
|
||||
assert type(y) is field
|
||||
|
||||
self.evalmap = dict(zip(xs, ys))
|
||||
|
||||
@classmethod
|
||||
def from_coeffs(cls, poly):
|
||||
assert type(poly) is _poly_coeff
|
||||
assert poly.degree() <= n
|
||||
padded_coeffs = poly.coefficients + [field(0)] * (n - len(poly.coefficients))
|
||||
ys = fft_helper(padded_coeffs, omega, field)
|
||||
xs = [omega**i for i in range(n) if ys[i] != 0]
|
||||
ys = [y for y in ys if y != 0]
|
||||
return cls(xs, ys)
|
||||
|
||||
def to_coeffs(self):
|
||||
# To convert back to the coefficient form, we use polynomial interpolation.
|
||||
# The non-zero elements stored in self.evalmap, so we fill in the zero values
|
||||
# here.
|
||||
ys = [self.evalmap[x] if x in self.evalmap else field(0) for x in _powers]
|
||||
coeffs = [b / field(n) for b in fft_helper(ys, 1 / omega, field)]
|
||||
return _poly_coeff(coeffs)
|
||||
|
||||
_lagrange_cache = {}
|
||||
def __call__(self, x):
|
||||
if type(x) is int:
|
||||
x = field(x)
|
||||
assert type(x) is field
|
||||
xs = _powers
|
||||
|
||||
def lagrange(x, xi):
|
||||
# Let's cache lagrange values
|
||||
if (x,xi) in PolynomialEvalRep._lagrange_cache:
|
||||
return PolynomialEvalRep._lagrange_cache[(x,xi)]
|
||||
|
||||
mul = lambda a,b: a*b
|
||||
num = reduce(mul, [x - xj for xj in xs if xj != xi], field(1))
|
||||
den = reduce(mul, [xi - xj for xj in xs if xj != xi], field(1))
|
||||
PolynomialEvalRep._lagrange_cache[(x,xi)] = num / den
|
||||
return PolynomialEvalRep._lagrange_cache[(x,xi)]
|
||||
|
||||
y = field(0)
|
||||
for xi, yi in self.evalmap.items():
|
||||
y += yi * lagrange(x, xi)
|
||||
return y
|
||||
|
||||
def __mul__(self, other):
|
||||
# Scale by integer
|
||||
if type(other) is int:
|
||||
other = field(other)
|
||||
if type(other) is field:
|
||||
return PolynomialEvalRep(self.evalmap.keys(),
|
||||
[other * y for y in self.evalmap.values()])
|
||||
|
||||
# Multiply another polynomial in the same representation
|
||||
if type(other) is type(self):
|
||||
xs = []
|
||||
ys = []
|
||||
for x, y in self.evalmap.items():
|
||||
if x in other.evalmap:
|
||||
xs.append(x)
|
||||
ys.append(y * other.evalmap[x])
|
||||
return PolynomialEvalRep(xs, ys)
|
||||
|
||||
@typecheck
|
||||
def __iadd__(self, other):
|
||||
# Add another polynomial to this one in place.
|
||||
# This is especially efficient when the other polynomial is sparse,
|
||||
# since we only need to add the non-zero elements.
|
||||
for x, y in other.evalmap.items():
|
||||
if x not in self.evalmap:
|
||||
self.evalmap[x] = y
|
||||
else:
|
||||
self.evalmap[x] += y
|
||||
return self
|
||||
|
||||
@typecheck
|
||||
def __add__(self, other):
|
||||
res = PolynomialEvalRep(self.evalmap.keys(), self.evalmap.values())
|
||||
res += other
|
||||
return res
|
||||
|
||||
def __sub__(self, other): return self + (-other)
|
||||
def __neg__(self): return PolynomialEvalRep(self.evalmap.keys(),
|
||||
[-y for y in self.evalmap.values()])
|
||||
|
||||
def __truediv__(self, divisor):
|
||||
# Scale by integer
|
||||
if type(divisor) is int:
|
||||
other = field(divisor)
|
||||
if type(divisor) is field:
|
||||
return self * (1/divisor)
|
||||
if type(divisor) is type(self):
|
||||
res = PolynomialEvalRep((),())
|
||||
for x, y in self.evalmap.items():
|
||||
assert x in divisor.evalmap
|
||||
res.evalmap[x] = y / divisor.evalmap[x]
|
||||
return res
|
||||
return NotImplemented
|
||||
|
||||
def __copy__(self):
|
||||
return PolynomialEvalRep(self.evalmap.keys(), self.evalmap.values())
|
||||
|
||||
def __repr__(self):
|
||||
return f'PolyEvalRep[{hex(omega.n)[:15]}...,{n}]({len(self.evalmap)} elements)'
|
||||
|
||||
@classmethod
|
||||
def divideWithCoset(cls, p, t, c=field(3)):
|
||||
"""
|
||||
This assumes that p and t are polynomials in coefficient representation,
|
||||
and that p is divisible by t.
|
||||
This function is useful when t has roots at some or all of the powers of omega,
|
||||
in which case we cannot just convert to evalrep and use division above
|
||||
(since it would cause a divide by zero.
|
||||
Instead, we evaluate p(X) at powers of (c*omega) for some constant cofactor c.
|
||||
To do this efficiently, we create new polynomials, pc(X) = p(cX), tc(X) = t(cX),
|
||||
and evaluate these at powers of omega. This conversion can be done efficiently
|
||||
on the coefficient representation.
|
||||
See also: cosetFFT in libsnark / libfqfft.
|
||||
https://github.com/scipr-lab/libfqfft/blob/master/libfqfft/evaluation_domain/domains/extended_radix2_domain.tcc
|
||||
"""
|
||||
assert type(p) is _poly_coeff
|
||||
assert type(t) is _poly_coeff
|
||||
# Compute p(cX), t(cX) by multiplying coefficients
|
||||
c_acc = field(1)
|
||||
pc = _poly_coeff(list(p.coefficients)) # make a copy
|
||||
for i in range(p.degree() + 1):
|
||||
pc.coefficients[-i-1] *= c_acc
|
||||
c_acc *= c
|
||||
c_acc = field(1)
|
||||
tc = _poly_coeff(list(t.coefficients)) # make a copy
|
||||
for i in range(t.degree() + 1):
|
||||
tc.coefficients[-i-1] *= c_acc
|
||||
c_acc *= c
|
||||
|
||||
# Divide using evalrep
|
||||
pc_rep = cls.from_coeffs(pc)
|
||||
tc_rep = cls.from_coeffs(tc)
|
||||
hc_rep = pc_rep / tc_rep
|
||||
hc = hc_rep.to_coeffs()
|
||||
|
||||
# Compute h(X) from h(cX) by dividing coefficients
|
||||
c_acc = field(1)
|
||||
h = _poly_coeff(list(hc.coefficients)) # make a copy
|
||||
for i in range(hc.degree() + 1):
|
||||
h.coefficients[-i-1] /= c_acc
|
||||
c_acc *= c
|
||||
|
||||
# Correctness checks
|
||||
# assert pc == tc * hc
|
||||
# assert p == t * h
|
||||
return h
|
||||
|
||||
|
||||
return PolynomialEvalRep
|
||||
|
||||
#| ## Sparse Matrix
|
||||
#| In our setting, we have O(m*m) elements in the matrix, and expect the number of
|
||||
#| elements to be O(m).
|
||||
#| In this setting, it's appropriate to use a rowdict representation - a dense
|
||||
#| array of dictionaries, one for each row, where the keys of each dictionary
|
||||
#| are column indices.
|
||||
|
||||
class RowDictSparseMatrix():
|
||||
# Only a few necessary methods are included here.
|
||||
# This could be replaced with a generic sparse matrix class, such as scipy.sparse,
|
||||
# but this does not work as well with custom value types like Fp
|
||||
|
||||
def __init__(self, m, n, zero=None):
|
||||
self.m = m
|
||||
self.n = n
|
||||
self.shape = (m,n)
|
||||
self.zero = zero
|
||||
self.rowdicts = [dict() for _ in range(m)]
|
||||
|
||||
def __setitem__(self, key, v):
|
||||
i, j = key
|
||||
self.rowdicts[i][j] = v
|
||||
|
||||
def __getitem__(self, key):
|
||||
i, j = key
|
||||
return self.rowdicts[i][j] if j in self.rowdicts[i] else self.zero
|
||||
|
||||
def items(self):
|
||||
for i in range(self.m):
|
||||
for j, v in self.rowdicts[i].items():
|
||||
yield (i,j), v
|
||||
|
||||
def dot(self, other):
|
||||
if isinstance(other, np.ndarray):
|
||||
assert other.dtype == 'O'
|
||||
assert other.shape in ((self.n,),(self.n,1))
|
||||
ret = np.empty((self.m,), dtype='O')
|
||||
ret.fill(self.zero)
|
||||
for i in range(self.m):
|
||||
for j, v in self.rowdicts[i].items():
|
||||
ret[i] += other[j] * v
|
||||
return ret
|
||||
|
||||
def to_dense(self):
|
||||
mat = np.empty((self.m, self.n), dtype='O')
|
||||
mat.fill(self.zero)
|
||||
for (i,j), val in self.items():
|
||||
mat[i,j] = val
|
||||
return mat
|
||||
|
||||
def __repr__(self): return repr(self.rowdicts)
|
||||
|
||||
#-
|
||||
# Examples
|
||||
if __name__ == '__main__':
|
||||
import misc
|
||||
|
||||
Fp = FiniteField(52435875175126190479447740508185965837690552500527637822603658699938581184513,1) # (# noqa: E501)
|
||||
Poly = polynomialsOver(Fp)
|
||||
|
||||
n = 8
|
||||
omega = misc.get_omega(Fp, n)
|
||||
PolyEvalRep = make_polynomial_evalrep(Fp, omega, n)
|
||||
|
||||
f = Poly([1,2,3,4,5])
|
||||
xs = tuple([omega**i for i in range(n)])
|
||||
ys = tuple(map(f, xs))
|
||||
# print('xs:', xs)
|
||||
# print('ys:', ys)
|
||||
|
||||
assert f == PolyEvalRep(xs, ys).to_coeffs()
|
||||
@@ -1,204 +0,0 @@
|
||||
# From the Sonic paper
|
||||
|
||||
from finite_fields import finitefield
|
||||
import numpy as np
|
||||
import misc
|
||||
|
||||
from multipoly import Variable, MultivariatePolynomial
|
||||
|
||||
p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
fp = finitefield.IntegersModP(p)
|
||||
|
||||
var_one = fp(1)
|
||||
var_x = fp(4)
|
||||
var_y = fp(6)
|
||||
var_s = fp(1)
|
||||
var_xy = var_x * var_y
|
||||
var_sxy = var_s * var_xy
|
||||
var_1_neg_s = var_one - var_s
|
||||
var_x_y = var_x + var_y
|
||||
var_1_neg_s_x_y = var_1_neg_s * var_x_y
|
||||
var_s_neg_1 = -var_1_neg_s
|
||||
var_zero = fp(0)
|
||||
|
||||
public_v = var_s * (var_x * var_y) + (1 - var_s) * (var_x + var_y)
|
||||
|
||||
a = np.array([
|
||||
var_one, var_x, var_xy, var_1_neg_s, var_s
|
||||
])
|
||||
b = np.array([
|
||||
var_one, var_y, var_s, var_x_y, var_s_neg_1
|
||||
])
|
||||
c = np.array([
|
||||
var_one, var_xy, var_sxy, var_1_neg_s_x_y, var_zero
|
||||
])
|
||||
assert len(a) == len(b)
|
||||
assert len(b) == len(c)
|
||||
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
try:
|
||||
assert a_i * b_i == c_i
|
||||
except AssertionError:
|
||||
print("Error for %i" % i)
|
||||
raise
|
||||
|
||||
# 1 - s = -(s - 1)
|
||||
u1 = np.array([0, 0, 0, 1, 0])
|
||||
v1 = np.array([0, 0, 0, 0, 1])
|
||||
w1 = np.array([0, 0, 0, 0, 0])
|
||||
k1 = 0
|
||||
|
||||
assert a.dot(u1) + b.dot(v1) + c.dot(w1) == k1
|
||||
|
||||
# xy = xy
|
||||
u2 = np.array([0, 0, 1, 0, 0])
|
||||
v2 = np.array([0, 0, 0, 0, 0])
|
||||
w2 = np.array([0, -1, 0, 0, 0])
|
||||
k2 = 0
|
||||
|
||||
assert a.dot(u2) + b.dot(v2) + c.dot(w2) == k2
|
||||
|
||||
# s = s
|
||||
u3 = np.array([0, 0, 0, 0, -1])
|
||||
v3 = np.array([0, 0, 1, 0, 0])
|
||||
w3 = np.array([0, 0, 0, 0, 0])
|
||||
k3 = 0
|
||||
|
||||
assert a.dot(u3) + b.dot(v3) + c.dot(w3) == k3
|
||||
|
||||
# zero = 0
|
||||
u4 = np.array([0, 0, 0, 0, 0])
|
||||
v4 = np.array([0, 0, 0, 0, 0])
|
||||
w4 = np.array([0, 0, 0, 0, 1])
|
||||
k4 = 0
|
||||
|
||||
assert a.dot(u4) + b.dot(v4) + c.dot(w4) == k4
|
||||
|
||||
# 1 - s
|
||||
u5 = np.array([1, 0, 0, -1, 0])
|
||||
v5 = np.array([0, 0, -1, 0, 0])
|
||||
w5 = np.array([0, 0, 0, 0, 0])
|
||||
k5 = 0
|
||||
|
||||
assert a.dot(u5) + b.dot(v5) + c.dot(w5) == k5
|
||||
|
||||
# x + y
|
||||
u6 = np.array([0, 1, 0, 0, 0])
|
||||
v6 = np.array([0, 1, 0, -1, 0])
|
||||
w6 = np.array([0, 0, 0, 0, 0])
|
||||
k6 = 0
|
||||
|
||||
assert a.dot(u6) + b.dot(v6) + c.dot(w6) == k6
|
||||
|
||||
# Final check:
|
||||
# v = s(xy) + (1 - s)(x + y)
|
||||
u7 = np.array([0, 0, 0, 0, 0])
|
||||
v7 = np.array([0, 0, 0, 0, 0])
|
||||
w7 = np.array([0, 0, 1, 1, 0])
|
||||
k7 = public_v
|
||||
|
||||
assert a.dot(u7) + b.dot(v7) + c.dot(w7) == k7
|
||||
|
||||
u = np.vstack((u1, u2, u3, u4, u5, u6, u7))
|
||||
v = np.vstack((v1, v2, v3, v4, v5, v6, v7))
|
||||
w = np.vstack((w1, w2, w3, w4, w5, w6, w7))
|
||||
assert u.shape == v.shape
|
||||
assert u.shape == w.shape
|
||||
|
||||
k = np.array((k1, k2, k3, k4, k5, k6, k7))
|
||||
|
||||
x = Variable("X", fp)
|
||||
y = Variable("Y", fp)
|
||||
p = MultivariatePolynomial()
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
#print(a_i, "\t", b_i, "\t", c_i)
|
||||
p += y**i * (a_i * b_i - c_i)
|
||||
assert not p
|
||||
|
||||
p = MultivariatePolynomial()
|
||||
for q, (u_q, v_q, w_q, k_q) in enumerate(zip(u, v, w, k)):
|
||||
p += y**q * (a.dot(u_q) + b.dot(v_q) + c.dot(w_q) - k_q)
|
||||
assert not p
|
||||
|
||||
n = len(a)
|
||||
assert len(b) == n
|
||||
assert len(c) == n
|
||||
|
||||
assert u.shape == (7, n)
|
||||
assert v.shape == u.shape
|
||||
assert w.shape == u.shape
|
||||
assert k.shape == (7,)
|
||||
|
||||
r_x_y = MultivariatePolynomial()
|
||||
s_x_y = MultivariatePolynomial()
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
assert 1 <= i <= n
|
||||
|
||||
r_x_y += x**i * y**i * a_i
|
||||
r_x_y += x**-i * y**-i * b_i
|
||||
r_x_y += x**(-i - n) * y**(-i - n) * c_i
|
||||
|
||||
u_i = u.T[i - 1]
|
||||
v_i = v.T[i - 1]
|
||||
w_i = w.T[i - 1]
|
||||
u_i_Y = MultivariatePolynomial()
|
||||
v_i_Y = MultivariatePolynomial()
|
||||
w_i_Y = MultivariatePolynomial()
|
||||
for q, (u_q_i, v_q_i, w_q_i) in enumerate(zip(u_i, v_i, w_i), 1):
|
||||
assert 1 <= q <= 7
|
||||
|
||||
u_i_Y += y**(q + n) * u_q_i
|
||||
v_i_Y += y**(q + n) * v_q_i
|
||||
w_i_Y += -y**i - y**(-i) + y**(q + n) * v_q_i
|
||||
|
||||
s_x_y += u_i_Y * x**-i + v_i_Y * x**i + w_i_Y * x**(i + n)
|
||||
|
||||
k_y = MultivariatePolynomial()
|
||||
for q, k_q in enumerate(k, 1):
|
||||
assert 1 <= q <= 7
|
||||
k_y += y**(q + n) * k_q
|
||||
|
||||
r_prime_x_y = r_x_y + s_x_y
|
||||
r_x_1 = r_x_y.evaluate({y.name: fp(1)})
|
||||
t_x_y = r_x_1 * r_prime_x_y - k_y
|
||||
t_x_y._assert_unique_terms()
|
||||
const_t = t_x_y.filter([x])
|
||||
print(const_t)
|
||||
|
||||
# Section 6, Figure 2
|
||||
#
|
||||
# zkP1
|
||||
# 4 blinding factors since we evaluate r(X, Y) 3 times
|
||||
# Blind r(X, Y)
|
||||
for i in range(1, 4):
|
||||
blind_c_i = misc.sample_random(fp)
|
||||
r_x_y += x**(-2*n - i) * y**(-2*n - i) * blind_c_i
|
||||
# Commit to r(X, Y)
|
||||
|
||||
# zkV1
|
||||
# Send a random y
|
||||
challenge_y = misc.sample_random(fp)
|
||||
|
||||
# zkP2
|
||||
# Commit to t(X, y)
|
||||
|
||||
# zkV2
|
||||
# Send a random z
|
||||
challenge_z = misc.sample_random(fp)
|
||||
|
||||
# zkP3
|
||||
# Evaluate a = r(z, 1)
|
||||
a = r_x_y.evaluate({x.name: challenge_z, y.name: fp(1)})
|
||||
# Evaluate b = r(z, y)
|
||||
b = r_x_y.evaluate({x.name: challenge_z, y.name: challenge_y})
|
||||
# Evaluate t = t(z, y)
|
||||
t = t_x_y.evaluate({x.name: challenge_z, y.name: challenge_y})
|
||||
# Evaluate s = s(z, y)
|
||||
s = s_x_y.evaluate({x.name: challenge_z, y.name: challenge_y})
|
||||
|
||||
# zkV3
|
||||
# Recalculate t from a, b and s
|
||||
k = k_y.evaluate({y.name: challenge_y})
|
||||
t = a * (b + s) - k
|
||||
# Verify polynomial commitments
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
import numpy as np
|
||||
from groth_poly_commit import K, create_proof, verify_proof
|
||||
|
||||
# Just use the same finite field we put in the polynomial commitment scheme file
|
||||
#p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
|
||||
#K = FiniteField(p)
|
||||
R.<x, y> = LaurentPolynomialRing(K)
|
||||
|
||||
var_one = K(1)
|
||||
var_x = K(4)
|
||||
var_y = K(6)
|
||||
var_s = K(1)
|
||||
var_xy = var_x * var_y
|
||||
var_sxy = var_s * var_xy
|
||||
var_1_neg_s = var_one - var_s
|
||||
var_x_y = var_x + var_y
|
||||
var_1_neg_s_x_y = var_1_neg_s * var_x_y
|
||||
var_s_neg_1 = -var_1_neg_s
|
||||
var_zero = K(0)
|
||||
|
||||
public_v = var_s * (var_x * var_y) + (1 - var_s) * (var_x + var_y)
|
||||
|
||||
a = np.array([
|
||||
var_one, var_x, var_xy, var_1_neg_s, var_s
|
||||
])
|
||||
b = np.array([
|
||||
var_one, var_y, var_s, var_x_y, var_s_neg_1
|
||||
])
|
||||
c = np.array([
|
||||
var_one, var_xy, var_sxy, var_1_neg_s_x_y, var_zero
|
||||
])
|
||||
assert len(a) == len(b)
|
||||
assert len(b) == len(c)
|
||||
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
try:
|
||||
assert a_i * b_i == c_i
|
||||
except AssertionError:
|
||||
print("Error for %i" % i)
|
||||
raise
|
||||
|
||||
# 1 - s = -(s - 1)
|
||||
u1 = np.array([0, 0, 0, 1, 0])
|
||||
v1 = np.array([0, 0, 0, 0, 1])
|
||||
w1 = np.array([0, 0, 0, 0, 0])
|
||||
k1 = 0
|
||||
|
||||
assert a.dot(u1) + b.dot(v1) + c.dot(w1) == k1
|
||||
|
||||
# xy = xy
|
||||
u2 = np.array([0, 0, 1, 0, 0])
|
||||
v2 = np.array([0, 0, 0, 0, 0])
|
||||
w2 = np.array([0, -1, 0, 0, 0])
|
||||
k2 = 0
|
||||
|
||||
assert a.dot(u2) + b.dot(v2) + c.dot(w2) == k2
|
||||
|
||||
# s = s
|
||||
u3 = np.array([0, 0, 0, 0, -1])
|
||||
v3 = np.array([0, 0, 1, 0, 0])
|
||||
w3 = np.array([0, 0, 0, 0, 0])
|
||||
k3 = 0
|
||||
|
||||
assert a.dot(u3) + b.dot(v3) + c.dot(w3) == k3
|
||||
|
||||
# zero = 0
|
||||
u4 = np.array([0, 0, 0, 0, 0])
|
||||
v4 = np.array([0, 0, 0, 0, 0])
|
||||
w4 = np.array([0, 0, 0, 0, 1])
|
||||
k4 = 0
|
||||
|
||||
assert a.dot(u4) + b.dot(v4) + c.dot(w4) == k4
|
||||
|
||||
# 1 - s
|
||||
u5 = np.array([1, 0, 0, -1, 0])
|
||||
v5 = np.array([0, 0, -1, 0, 0])
|
||||
w5 = np.array([0, 0, 0, 0, 0])
|
||||
k5 = 0
|
||||
|
||||
assert a.dot(u5) + b.dot(v5) + c.dot(w5) == k5
|
||||
|
||||
# x + y
|
||||
u6 = np.array([0, 1, 0, 0, 0])
|
||||
v6 = np.array([0, 1, 0, -1, 0])
|
||||
w6 = np.array([0, 0, 0, 0, 0])
|
||||
k6 = 0
|
||||
|
||||
assert a.dot(u6) + b.dot(v6) + c.dot(w6) == k6
|
||||
|
||||
# Final check:
|
||||
# v = s(xy) + (1 - s)(x + y)
|
||||
u7 = np.array([0, 0, 0, 0, 0])
|
||||
v7 = np.array([0, 0, 0, 0, 0])
|
||||
w7 = np.array([0, 0, 1, 1, 0])
|
||||
k7 = public_v
|
||||
|
||||
assert a.dot(u7) + b.dot(v7) + c.dot(w7) == k7
|
||||
|
||||
u = np.vstack((u1, u2, u3, u4, u5, u6, u7))
|
||||
v = np.vstack((v1, v2, v3, v4, v5, v6, v7))
|
||||
w = np.vstack((w1, w2, w3, w4, w5, w6, w7))
|
||||
assert u.shape == v.shape
|
||||
assert u.shape == w.shape
|
||||
|
||||
k = np.array((k1, k2, k3, k4, k5, k6, k7))
|
||||
|
||||
p = K(0)
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
#print(a_i, "\t", b_i, "\t", c_i)
|
||||
p += y**i * (a_i * b_i - c_i)
|
||||
print(p)
|
||||
|
||||
p = K(0)
|
||||
for q, (u_q, v_q, w_q, k_q) in enumerate(zip(u, v, w, k)):
|
||||
p += y**q * (a.dot(u_q) + b.dot(v_q) + c.dot(w_q) - k_q)
|
||||
print(p)
|
||||
|
||||
n = len(a)
|
||||
assert len(b) == n
|
||||
assert len(c) == n
|
||||
|
||||
assert u.shape == (7, n)
|
||||
assert v.shape == u.shape
|
||||
assert w.shape == u.shape
|
||||
assert k.shape == (7,)
|
||||
|
||||
r_x_y = 0
|
||||
s_x_y = 0
|
||||
for i, (a_i, b_i, c_i) in enumerate(zip(a, b, c), 1):
|
||||
assert 1 <= i <= n
|
||||
|
||||
r_x_y += x**i * y**i * a_i
|
||||
r_x_y += x**-i * y**-i * b_i
|
||||
r_x_y += x**(-i - n) * y**(-i - n) * c_i
|
||||
|
||||
u_i = u.T[i - 1]
|
||||
v_i = v.T[i - 1]
|
||||
w_i = w.T[i - 1]
|
||||
u_i_Y = 0
|
||||
v_i_Y = 0
|
||||
w_i_Y = 0
|
||||
for q, (u_q_i, v_q_i, w_q_i) in enumerate(zip(u_i, v_i, w_i), 1):
|
||||
assert 1 <= q <= 7
|
||||
|
||||
u_i_Y += y**(q + n) * u_q_i
|
||||
v_i_Y += y**(q + n) * v_q_i
|
||||
w_i_Y += -y**i - y**(-i) + y**(q + n) * w_q_i
|
||||
|
||||
s_x_y += u_i_Y * x**-i + v_i_Y * x**i + w_i_Y * x**(i + n)
|
||||
|
||||
k_y = 0
|
||||
for q, k_q in enumerate(k, 1):
|
||||
assert 1 <= q <= 7
|
||||
k_y += y**(q + n) * k_q
|
||||
|
||||
# Section 6, Figure 2
|
||||
#
|
||||
# zkP1
|
||||
# 4 blinding factors since we evaluate r(X, Y) 3 times
|
||||
# Blind r(X, Y)
|
||||
#for i in range(1, 4 + 1):
|
||||
# blind_c_i = K.random_element()
|
||||
# r_x_y += x**(-2*n - i) * y**(-2*n - i) * blind_c_i
|
||||
# Commit to r(X, Y)
|
||||
|
||||
r_prime_x_y = r_x_y + s_x_y
|
||||
r_x_1 = r_x_y(y=K(1))
|
||||
t_x_y = r_x_1 * r_prime_x_y - k_y
|
||||
print(t_x_y.constant_coefficient())
|
||||
|
||||
# zkV1
|
||||
# Send a random y
|
||||
challenge_y = K.random_element()
|
||||
|
||||
# zkP2
|
||||
# Commit to t(X, y)
|
||||
t_x = t_x_y(y=challenge_y)
|
||||
t_x = t_x.univariate_polynomial()
|
||||
print(t_x.constant_coefficient())
|
||||
|
||||
# zkV2
|
||||
# Send a random z
|
||||
challenge_z = K.random_element()
|
||||
|
||||
# zkP3
|
||||
# Evaluate a = r(z, 1)
|
||||
a = r_x_y(x=challenge_z, y=K(1))
|
||||
# Evaluate b = r(z, y)
|
||||
b = r_x_y(x=challenge_z, y=challenge_y)
|
||||
# Evaluate t = t(z, y)
|
||||
t = t_x_y(x=challenge_z, y=challenge_y)
|
||||
# Evaluate s = s(z, y)
|
||||
s = s_x_y(x=challenge_z, y=challenge_y)
|
||||
|
||||
# zkV3
|
||||
# Recalculate t from a, b and s
|
||||
k = k_y(y=challenge_y)
|
||||
t_new = a * (b + s) - k
|
||||
assert t_new == t
|
||||
# Verify polynomial commitments
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import random
|
||||
import misc
|
||||
import pasta
|
||||
from polynomial_evalrep import make_polynomial_evalrep
|
||||
|
||||
n = 8
|
||||
omega_base = misc.get_omega(pasta.fp, 2**32, seed=0)
|
||||
assert misc.is_power_of_two(8)
|
||||
omega = omega_base ** (2 ** 32 // n)
|
||||
# Order of omega is n
|
||||
assert omega ** n == 1
|
||||
# Compute complete roots of this group
|
||||
ROOTS = [omega ** i for i in range(n)]
|
||||
|
||||
PolyEvalRep = make_polynomial_evalrep(pasta.fp, omega, n)
|
||||
|
||||
import numpy as np
|
||||
from tabulate import tabulate
|
||||
|
||||
# Wires
|
||||
a = ["x", "v1", "v2", "1", "1", "v3", "e1", "e2"]
|
||||
b = ["x", "x", "x", "5", "35", "5", "e3", "e4"]
|
||||
c = ["v1", "v2", "v3", "5", "35", "35", "e5", "e6"]
|
||||
|
||||
wires = a + b + c
|
||||
|
||||
# Gates
|
||||
# La + Rb + Oc + Mab + C = 0
|
||||
add = np.array([1, 1, 0, -1, 0])
|
||||
mul = np.array([0, 0, 1, -1, 0])
|
||||
const5 = np.array([0, 1, 0, 0, -5])
|
||||
public_input = np.array([0, 1, 0, 0, 0])
|
||||
empty = np.array([0, 0, 0, 0, 0])
|
||||
|
||||
gates_matrix = np.array(
|
||||
[mul, mul, add, const5, public_input, add, empty, empty])
|
||||
print("Wires:")
|
||||
print(tabulate([["a ="] + a, ["b ="] + b, ["c ="] + c]))
|
||||
print()
|
||||
print("Gates:")
|
||||
print(gates_matrix)
|
||||
print()
|
||||
|
||||
# The index of the public input in the gates_matrix
|
||||
# We specify its position and its value
|
||||
public_input_values = [(4, 35)]
|
||||
|
||||
def permute_indices(wires):
|
||||
size = len(wires)
|
||||
permutation = [i + 1 for i in range(size)]
|
||||
for i in range(size):
|
||||
for j in range(i + 1, size):
|
||||
if wires[i] == wires[j]:
|
||||
permutation[i], permutation[j] = permutation[j], permutation[i]
|
||||
break
|
||||
return permutation
|
||||
|
||||
permutation = permute_indices(wires)
|
||||
|
||||
table = [
|
||||
["Wires"] + wires,
|
||||
["Indices"] + list(i + 1 for i in range(len(wires))),
|
||||
["Permutations"] + permutation
|
||||
]
|
||||
print(tabulate(table))
|
||||
print()
|
||||
|
||||
import misc
|
||||
from pasta import fp
|
||||
|
||||
def setup(wires, gates_matrix):
|
||||
# Section 8.1
|
||||
# The selector polynomials that define the circuit's arithmetisation
|
||||
gates_matrix = gates_matrix.transpose()
|
||||
ql = PolyEvalRep(ROOTS, [fp(i) for i in gates_matrix[0]])
|
||||
qr = PolyEvalRep(ROOTS, [fp(i) for i in gates_matrix[1]])
|
||||
qm = PolyEvalRep(ROOTS, [fp(i) for i in gates_matrix[2]])
|
||||
qo = PolyEvalRep(ROOTS, [fp(i) for i in gates_matrix[3]])
|
||||
qc = PolyEvalRep(ROOTS, [fp(i) for i in gates_matrix[4]])
|
||||
selector_polys = [ql, qr, qm, qo, qc]
|
||||
|
||||
public_input = [fp(0) for i in range(len(ROOTS))]
|
||||
for (index, value) in public_input_values:
|
||||
# This is negative because the value is added to
|
||||
# the output of the const selector poly:
|
||||
# La + Rb + Oc + Mab + (C + PI) = 0
|
||||
public_input[index] = fp(-value)
|
||||
public_input_poly = PolyEvalRep(ROOTS, public_input)
|
||||
|
||||
# Identity permutations applied to a, b, c
|
||||
# Ideally H, k_1 H, k_2 H are distinct cosets of H
|
||||
# Here we just sample k and assume it's high-order
|
||||
# Random high order k to form distinct cosets
|
||||
k = misc.sample_random(fp)
|
||||
id_domain_a = ROOTS
|
||||
id_domain_b = [k * root for root in ROOTS]
|
||||
id_domain_c = [k**2 * root for root in ROOTS]
|
||||
id_domain = id_domain_a + id_domain_b + id_domain_c
|
||||
|
||||
# Intermediate step where we permute the positions of the domain
|
||||
# generated above
|
||||
permuted_domain = [id_domain[i - 1] for i in permutation]
|
||||
permuted_domain_a = permuted_domain[:n]
|
||||
permuted_domain_b = permuted_domain[n:2 * n]
|
||||
permuted_domain_c = permuted_domain[2*n:3 * n]
|
||||
|
||||
# The copy permuation applied to a, b, c
|
||||
# Returns the permuted index value (corresponding root of unity coset)
|
||||
# when evaluated on the domain.
|
||||
ssigma_1 = PolyEvalRep(ROOTS, permuted_domain_a)
|
||||
ssigma_2 = PolyEvalRep(ROOTS, permuted_domain_b)
|
||||
ssigma_3 = PolyEvalRep(ROOTS, permuted_domain_c)
|
||||
copy_permutes = [ssigma_1, ssigma_2, ssigma_3]
|
||||
|
||||
setup(wires, gates_matrix)
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
from finite_fields.modp import IntegersModP
|
||||
|
||||
q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
|
||||
modq = IntegersModP(q)
|
||||
|
||||
a = modq(-1)
|
||||
print("a:", hex(a.n))
|
||||
d = -(modq(10240)/modq(10241))
|
||||
params = (a, d)
|
||||
|
||||
def is_jubjub(params, x, y):
|
||||
a, d = params
|
||||
|
||||
return a * x**2 + y**2 == 1 + d * x**2 * y**2
|
||||
|
||||
def add(params, point_1, point_2):
|
||||
# From here: https://z.cash/technology/jubjub/
|
||||
|
||||
a, d = params
|
||||
|
||||
x1, y1 = point_1
|
||||
x2, y2 = point_2
|
||||
|
||||
x3 = (x1 * y2 + y1 * x2) / (1 + d * x1 * x2 * y1 * y2)
|
||||
y3 = (y1 * y2 + x1 * x2) / (1 - d * x1 * x2 * y1 * y2)
|
||||
|
||||
return (x3, y3)
|
||||
|
||||
def fake_zk_add(params, point_1, point_2):
|
||||
# From here: https://z.cash/technology/jubjub/
|
||||
|
||||
a, d = params
|
||||
|
||||
x1, y1 = point_1
|
||||
x2, y2 = point_2
|
||||
|
||||
# Compute U = (u1 + v1) * (v2 - EDWARDS_A*u2)
|
||||
# = (u1 + v1) * (u2 + v2)
|
||||
U = (x1 + y1) * (x2 + y2)
|
||||
assert (x1 + y1) * (x2 + y2) == U
|
||||
|
||||
# Compute A = v2 * u1
|
||||
A = y2 * x1
|
||||
# Compute B = u2 * v1
|
||||
B = x2 * y1
|
||||
# Compute C = d*A*B
|
||||
C = d * A * B
|
||||
assert (d * A) * (B) == C
|
||||
|
||||
# Compute u3 = (A + B) / (1 + C)
|
||||
# NOTE: make sure we check for (1 + C) has an inverse
|
||||
u3 = (A + B) / (1 + C)
|
||||
assert (1 + C) * (u3) == (A + B)
|
||||
|
||||
# Compute v3 = (U - A - B) / (1 - C)
|
||||
# We will also need to check inverse here as well.
|
||||
v3 = (U - A - B) / (1 - C)
|
||||
assert (1 - C) * (v3) == (U - A - B)
|
||||
|
||||
return u3, v3
|
||||
|
||||
x = 0x15a36d1f0f390d8852a35a8c1908dd87a361ee3fd48fdf77b9819dc82d90607e
|
||||
y = 0x015d8c7f5b43fe33f7891142c001d9251f3abeeb98fad3e87b0dc53c4ebf1891
|
||||
|
||||
x3, y3 = add(params, (x, y), (x, y))
|
||||
print(hex(x3.n), hex(y3.n))
|
||||
u3, v3 = fake_zk_add(params, (x, y), (x, y))
|
||||
print(hex(u3.n), hex(v3.n))
|
||||
|
||||
print(is_jubjub(params, x, y))
|
||||
print(is_jubjub(params, x3, y3))
|
||||
|
||||
print()
|
||||
print("Identity (0, 1) is jubjub?", is_jubjub(params, 0, 1))
|
||||
print("Torsion (0, -1) is jubjub?", is_jubjub(params, 0, -1))
|
||||
double_torsion = add(params, (0, -1), (0, -1))
|
||||
print("Double torsion is:", hex(double_torsion[0].n), hex(double_torsion[1].n))
|
||||
dbl_ident = add(params, (0, 1), (0, 1))
|
||||
print("Double identity is:", hex(dbl_ident[0].n), hex(dbl_ident[1].n))
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
from finite_fields.modp import IntegersModP
|
||||
|
||||
q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
|
||||
modq = IntegersModP(q)
|
||||
|
||||
a = modq(-1)
|
||||
print("0x%x" % a.n)
|
||||
print("\n")
|
||||
two = modq(2)
|
||||
inv2 = modq(2).inverse()
|
||||
print("Inverse of 2 = 0x%x" % inv2.n)
|
||||
print((two * inv2))
|
||||
# This is from bellman
|
||||
inv2_bellman = 0x39f6d3a994cebea4199cec0404d0ec02a9ded2017fff2dff7fffffff80000001
|
||||
assert inv2.n == inv2_bellman
|
||||
assert (2 * inv2.n) % q == 1
|
||||
|
||||
# Futures contract calculation
|
||||
multiplier = modq(1)
|
||||
quantity = modq(100)
|
||||
entry_price = modq(10000)
|
||||
exit_price = modq(15000)
|
||||
|
||||
initial_margin = multiplier * quantity
|
||||
print("initial margin =", initial_margin)
|
||||
price_return = exit_price * entry_price.inverse()
|
||||
print("R =", price_return)
|
||||
pnl = initial_margin - (initial_margin * exit_price) * entry_price.inverse()
|
||||
print("PNL =", pnl)
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
import asyncio
|
||||
from tabulate import tabulate
|
||||
from copy import deepcopy
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
lock = asyncio.Lock()
|
||||
logs_path = "/tmp/darkfi/"
|
||||
|
||||
node_info = {
|
||||
}
|
||||
|
||||
ping_times = {
|
||||
}
|
||||
|
||||
def debug(line):
|
||||
#print(line)
|
||||
pass
|
||||
|
||||
def process(info, line):
|
||||
regex_listen = re.compile(
|
||||
".* Listening on (\d+[.]\d+[.]\d+[.]\d+:\d+)")
|
||||
regex_inbound_connect = re.compile(
|
||||
".* Connected inbound \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
|
||||
regex_outbound_slots = re.compile(
|
||||
".* Starting (\d+) outbound connection slots.")
|
||||
regex_outbound_connect = re.compile(
|
||||
".* #(\d+) connected to outbound \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
|
||||
regex_channel_disconnected = re.compile(
|
||||
".* Channel (\d+[.]\d+[.]\d+[.]\d+:\d+) disconnected")
|
||||
regex_pong_recv = re.compile(
|
||||
".* Received Pong message (\d+)ms from \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
|
||||
|
||||
if "net: P2p::start() [BEGIN]" in line:
|
||||
info["status"] = "p2p-start"
|
||||
elif "net: SeedSession::start() [START]" in line:
|
||||
info["status"] = "seed-start"
|
||||
elif "net: SeedSession::start() [END]" in line:
|
||||
info["status"] = "seed-done"
|
||||
elif "net: P2p::start() [END]" in line:
|
||||
info["status"] = "p2p-done"
|
||||
elif "net: P2p::run() [BEGIN]" in line:
|
||||
info["status"] = "p2p-run"
|
||||
elif "Not configured for accepting incoming connections." in line:
|
||||
info["inbounds"] = ["Disabled"]
|
||||
elif (match := regex_listen.match(line)) is not None:
|
||||
address = match.group(1)
|
||||
info["listen"] = address
|
||||
elif (match := regex_inbound_connect.match(line)) is not None:
|
||||
address = match.group(1)
|
||||
info["inbounds"].append(address)
|
||||
elif (match := regex_outbound_slots.match(line)) is not None:
|
||||
slots = match.group(1)
|
||||
info["outbounds"] = ["None" for _ in range(int(slots))]
|
||||
elif (match := regex_outbound_connect.match(line)) is not None:
|
||||
slot = match.group(1)
|
||||
address = match.group(2)
|
||||
info["outbounds"][int(slot)] = address
|
||||
elif (match := regex_channel_disconnected.match(line)) is not None:
|
||||
address = match.group(1)
|
||||
try:
|
||||
info["inbounds"].remove(address)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
idx = info["outbounds"].index(address)
|
||||
info["outbounds"][idx] = "None"
|
||||
except ValueError:
|
||||
pass
|
||||
elif (match := regex_pong_recv.match(line)) is not None:
|
||||
ping_time = match.group(1)
|
||||
address = match.group(2)
|
||||
ping_times[address] = ping_time
|
||||
|
||||
async def scanner(filename):
|
||||
global table_data
|
||||
|
||||
async with lock:
|
||||
node_info[filename] = {
|
||||
"status": "none",
|
||||
"inbounds": [],
|
||||
"outbounds": [],
|
||||
}
|
||||
info = node_info[filename]
|
||||
|
||||
with open(logs_path + filename) as fileh:
|
||||
while True:
|
||||
line = fileh.readline()
|
||||
if line:
|
||||
debug("R: " + filename + ": " + line[:-1])
|
||||
async with lock:
|
||||
process(info, line)
|
||||
else:
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
def clear_lines(n):
|
||||
for i in range(n):
|
||||
sys.stdout.write('\033[F')
|
||||
|
||||
def get_ping(addr):
|
||||
ping_time = "none"
|
||||
if addr in ping_times:
|
||||
ping_time = str(ping_times[addr]) + " ms"
|
||||
return ping_time
|
||||
|
||||
def table_format(ninfo):
|
||||
table_data = []
|
||||
for filename, info in ninfo.items():
|
||||
table_data.append([filename, "", ""])
|
||||
table_data.append(["", "status", info["status"]])
|
||||
|
||||
if "listen" in info:
|
||||
table_data.append(["", "listen", info["listen"]])
|
||||
|
||||
inbounds = info["inbounds"]
|
||||
if inbounds:
|
||||
table_data.append(["", "inbounds", inbounds[0],
|
||||
get_ping(inbounds[0])])
|
||||
|
||||
for inbound in inbounds[1:]:
|
||||
table_data.append(["", "", inbound, get_ping(inbound)])
|
||||
|
||||
outbounds = info["outbounds"]
|
||||
if outbounds:
|
||||
table_data.append(["", "outbounds", outbounds[0],
|
||||
get_ping(outbounds[0])])
|
||||
|
||||
for outbound in outbounds[1:]:
|
||||
table_data.append(["", "", outbound, get_ping(outbound)])
|
||||
|
||||
headers = ["Name", "Attribute", "Value", "Ping Times"]
|
||||
return headers, table_data
|
||||
|
||||
async def refresh_table(tick=1):
|
||||
for filename in os.listdir(logs_path):
|
||||
asyncio.create_task(scanner(filename))
|
||||
|
||||
previous_lines = 0
|
||||
|
||||
while True:
|
||||
clear_lines(previous_lines)
|
||||
|
||||
async with lock:
|
||||
ninfo = deepcopy(node_info)
|
||||
headers, table_data = table_format(ninfo)
|
||||
lines = tabulate(table_data, headers=headers).split("\n")
|
||||
debug("-------------------")
|
||||
for line in lines:
|
||||
print('\x1b[2K\r', end="")
|
||||
print(line)
|
||||
|
||||
previous_lines = len(lines)
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
||||
asyncio.run(refresh_table())
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
python scripts/parser.py proofs/sapling3.prf | rustfmt > proofs/sapling3.rs
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/pism.py proofs/simple.pism | rustfmt > src/simple_circuit.rs
|
||||
cargo run --release --bin simple
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Dark Client
|
||||
|
||||
$ python3 -m venv env
|
||||
$ source env/bin/activate
|
||||
$ pip install -r requirements.txt
|
||||
Binary file not shown.
@@ -1,89 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from util import arg_parser
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
|
||||
class DarkClient:
|
||||
# TODO: generate random ID (4 byte unsigned int) (rand range 0 - max size
|
||||
# uint32
|
||||
def __init__(self, client_session):
|
||||
self.url = "http://localhost:8000/"
|
||||
self.client_session = client_session
|
||||
self.payload = {
|
||||
"method": [],
|
||||
"params": [],
|
||||
"jsonrpc": [],
|
||||
"id": [],
|
||||
}
|
||||
|
||||
async def key_gen(self, payload):
|
||||
payload['method'] = "key_gen"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
key = await self.__request(payload)
|
||||
print(key)
|
||||
|
||||
async def get_info(self, payload):
|
||||
payload['method'] = "get_info"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
info = await self.__request(payload)
|
||||
print(info)
|
||||
|
||||
async def stop(self, payload):
|
||||
payload['method'] = "stop"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
stop = await self.__request(payload)
|
||||
print(stop)
|
||||
|
||||
async def say_hello(self, payload):
|
||||
payload['method'] = "say_hello"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
hello = await self.__request(payload)
|
||||
print(hello)
|
||||
|
||||
async def create_wallet(self, payload):
|
||||
payload['method'] = "create_wallet"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
wallet = await self.__request(payload)
|
||||
print(wallet)
|
||||
|
||||
async def create_cashier_wallet(self, payload):
|
||||
payload['method'] = "create_cashier_wallet"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
wallet = await self.__request(payload)
|
||||
print(wallet)
|
||||
|
||||
async def test_wallet(self, payload):
|
||||
payload['method'] = "test_wallet"
|
||||
payload['jsonrpc'] = "2.0"
|
||||
payload['id'] = "0"
|
||||
test = await self.__request(payload)
|
||||
print(test)
|
||||
|
||||
async def __request(self, payload):
|
||||
async with self.client_session.post(self.url, json=payload) as response:
|
||||
resp = await response.text()
|
||||
print(resp)
|
||||
|
||||
async def main():
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
client = DarkClient(session)
|
||||
await arg_parser(client)
|
||||
except aiohttp.ClientConnectorError as err:
|
||||
print('CONNECTION ERROR:', str(err))
|
||||
except Exception as err:
|
||||
print("ERROR: ", str(err))
|
||||
|
||||
if __name__ == "__main__":
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
aiodns==3.0.0
|
||||
aiohttp==3.7.4.post0
|
||||
async-timeout==3.0.1
|
||||
attrs==21.2.0
|
||||
brotlipy==0.7.0
|
||||
cchardet==2.1.7
|
||||
cffi==1.14.5
|
||||
chardet==4.0.0
|
||||
idna==3.2
|
||||
multidict==5.1.0
|
||||
pycares==4.0.0
|
||||
pycparser==2.20
|
||||
typing-extensions==3.10.0.0
|
||||
yarl==1.6.3
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
import argparse
|
||||
|
||||
async def arg_parser(client):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='drk',
|
||||
usage='%(prog)s [commands]',
|
||||
description="""DarkFi wallet command-line tool"""
|
||||
)
|
||||
|
||||
parser.add_argument('-c', '--cashier', action='store_true', help='Create a cashier wallet')
|
||||
parser.add_argument('-w', '--wallet', action='store_true', help='Create a new wallet')
|
||||
parser.add_argument('-k', '--key', action='store_true', help='Test key')
|
||||
parser.add_argument('-i', '--info', action='store_true', help='Request info from daemon')
|
||||
parser.add_argument('-hi', '--hello', action='store_true', help='Test hello')
|
||||
parser.add_argument("-s", "--stop", action='store_true', help="Send a stop signal to the daemon")
|
||||
parser.add_argument("-t", "--test", action='store_true', help="Test writing to the wallet")
|
||||
|
||||
try:
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.key:
|
||||
print("Attemping to generate a create key pair...")
|
||||
await client.key_gen(client.payload)
|
||||
|
||||
if args.wallet:
|
||||
print("Attemping to create a wallet...")
|
||||
await client.create_wallet(client.payload)
|
||||
|
||||
if args.info:
|
||||
print("Info was entered")
|
||||
await client.get_info(client.payload)
|
||||
print("Requesting daemon info...")
|
||||
|
||||
if args.stop:
|
||||
print("Stop was entered")
|
||||
await client.stop(client.payload)
|
||||
print("Sending a stop signal...")
|
||||
|
||||
if args.hello:
|
||||
print("Hello was entered")
|
||||
await client.say_hello(client.payload)
|
||||
|
||||
if args.cashier:
|
||||
print("Attempting to generate a cashier wallet...")
|
||||
await client.create_cashier_wallet(client.payload)
|
||||
|
||||
if args.test:
|
||||
print("Testing wallet write")
|
||||
await client.test_wallet(client.payload)
|
||||
|
||||
except Exception:
|
||||
raise
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/bits.psm > /tmp/bits.psm
|
||||
python scripts/vm.py --rust /tmp/bits.psm > src/bits_contract.rs
|
||||
cargo run --release --bin bits
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/mimc.psm > /tmp/mimc.psm
|
||||
python scripts/vm.py --rust /tmp/mimc.psm > src/zkmimc_contract.rs
|
||||
cargo run --release --bin zkmimc
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/mint2.psm > /tmp/mint2.psm || exit $?
|
||||
python scripts/vm.py --rust /tmp/mint2.psm > src/mint2_contract.rs || exit $?
|
||||
cargo run --release --bin mint2
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/mint.pism > /tmp/mint.pism
|
||||
python scripts/pism.py /tmp/mint.pism proofs/mint.aux | rustfmt > src/mint_contract.rs
|
||||
cargo run --release --bin mint
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/spend.pism > /tmp/spend.pism
|
||||
python scripts/pism.py /tmp/spend.pism proofs/mint.aux | rustfmt > src/spend_contract.rs
|
||||
cargo run --release --bin spend
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
python scripts/preprocess.py proofs/jubjub.pism > /tmp/jubjub.pism
|
||||
python scripts/vm.py --rust /tmp/jubjub.pism > src/vm_load.rs
|
||||
cargo run --release --bin vmtest
|
||||
|
||||
@@ -1,835 +0,0 @@
|
||||
import lark
|
||||
import pprint
|
||||
import re
|
||||
import sys
|
||||
|
||||
class LineDesc:
|
||||
|
||||
def __init__(self, level, text, lineno):
|
||||
self.level = level
|
||||
self.text = text
|
||||
self.lineno = lineno
|
||||
assert self.text[0] != ' '
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s:'%s'>" % (self.level, self.text)
|
||||
|
||||
def clean_line(line):
|
||||
lead_spaces = len(line) - len(line.lstrip(" "))
|
||||
level = lead_spaces / 4
|
||||
# Remove leading spaces
|
||||
if line.strip(" ") == "":
|
||||
return None
|
||||
line = line.lstrip(" ")
|
||||
# Remove all comments
|
||||
line = re.sub('#.*$', '', line).strip()
|
||||
if not line:
|
||||
return None
|
||||
return level, line
|
||||
|
||||
def parse(text):
|
||||
lines = text.split("\n")
|
||||
|
||||
linedescs = []
|
||||
|
||||
# These are to join open parenthesis
|
||||
current_line = ""
|
||||
paren_level = 0
|
||||
|
||||
for lineno, line in enumerate(lines):
|
||||
if (lineinfo := clean_line(line)) is None:
|
||||
continue
|
||||
level, line = lineinfo
|
||||
|
||||
for c in line:
|
||||
if c == "(":
|
||||
paren_level += 1
|
||||
elif c == ")":
|
||||
paren_level -= 1
|
||||
|
||||
#print(level, paren_level, current_line)
|
||||
|
||||
if paren_level < 0:
|
||||
print("error: too many closing paren )", file=sys.stderr)
|
||||
print("line:", lineno)
|
||||
return
|
||||
|
||||
if current_line:
|
||||
current_line += " " + line
|
||||
else:
|
||||
current_line = line
|
||||
|
||||
if paren_level > 0:
|
||||
continue
|
||||
|
||||
#print(level, current_line)
|
||||
|
||||
ldesc = LineDesc(level, current_line, lineno)
|
||||
linedescs.append(ldesc)
|
||||
|
||||
current_line = ""
|
||||
|
||||
if paren_level > 0:
|
||||
print("error: missing closing paren )", file=sys.stderr)
|
||||
return None
|
||||
|
||||
return linedescs
|
||||
|
||||
def section(linedescs):
|
||||
sections = []
|
||||
|
||||
current_section = None
|
||||
for desc in linedescs:
|
||||
if desc.level == 0:
|
||||
if current_section:
|
||||
sections.append(current_section)
|
||||
current_section = [desc]
|
||||
continue
|
||||
|
||||
current_section.append(desc)
|
||||
sections.append(current_section)
|
||||
|
||||
return sections
|
||||
|
||||
def classify(sections):
|
||||
consts = []
|
||||
funcs = []
|
||||
contracts = []
|
||||
|
||||
for section in sections:
|
||||
assert len(section)
|
||||
|
||||
if section[0].text == "const:":
|
||||
consts.append(section)
|
||||
elif section[0].text.startswith("def"):
|
||||
funcs.append(section)
|
||||
elif section[0].text.startswith("contract"):
|
||||
contracts.append(section)
|
||||
|
||||
return consts, funcs, contracts
|
||||
|
||||
def tokenize_const(text):
|
||||
parser = lark.Lark(r"""
|
||||
value_map: name ":" type_def
|
||||
|
||||
name: NAME
|
||||
|
||||
?type_def: point
|
||||
| blake2s_personalization
|
||||
| pedersen_personalization
|
||||
| list
|
||||
|
||||
point: "Point"
|
||||
|
||||
blake2s_personalization: "Blake2sPersonalization"
|
||||
|
||||
pedersen_personalization: "PedersenPersonalization"
|
||||
|
||||
list: "list<" type_def ">"
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
""", start="value_map")
|
||||
return parser.parse(text)
|
||||
|
||||
class ConstTransformer(lark.Transformer):
|
||||
def name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def point(self, _):
|
||||
return "Point"
|
||||
def blake2s_personalization(self, _):
|
||||
return "Blake2sPersonalization"
|
||||
def pedersen_personalization(self, _):
|
||||
return "PedersenPersonalization"
|
||||
value_map = tuple
|
||||
list = list
|
||||
|
||||
def read_consts(consts):
|
||||
consts_map = {}
|
||||
|
||||
for subsection in consts:
|
||||
assert subsection[0].text == "const:"
|
||||
|
||||
for ldesc in subsection[1:]:
|
||||
tree = tokenize_const(ldesc.text)
|
||||
tokens = ConstTransformer().transform(tree)
|
||||
#print(tokens)
|
||||
name, typedesc = tokens
|
||||
consts_map[name] = typedesc
|
||||
|
||||
#pprint.pprint(consts_map)
|
||||
return consts_map
|
||||
|
||||
class FuncDefTransformer(lark.Transformer):
|
||||
def func_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def param(self, obj):
|
||||
return tuple(obj)
|
||||
|
||||
def param_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def u64(self, _):
|
||||
return "U64"
|
||||
def scalar(self, _):
|
||||
return "Scalar"
|
||||
def point(self, _):
|
||||
return "Point"
|
||||
def binary(self, _):
|
||||
return "Binary"
|
||||
|
||||
def type(self, obj):
|
||||
return obj[0]
|
||||
|
||||
func_def = list
|
||||
params = list
|
||||
type_list = list
|
||||
|
||||
def parse_func_def(text):
|
||||
parser = lark.Lark(r"""
|
||||
func_def: "def" func_name "(" params+ ")" "->" type_list ":"
|
||||
|
||||
func_name: NAME
|
||||
params: param ("," param)*
|
||||
|
||||
type_list: type
|
||||
| "(" type ("," type)* ")"
|
||||
|
||||
param: param_name ":" type
|
||||
param_name: NAME
|
||||
|
||||
type: u64 | scalar | point | binary
|
||||
|
||||
u64: "U64"
|
||||
scalar: "Scalar"
|
||||
point: "Point"
|
||||
binary: "Binary"
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
""", start="func_def")
|
||||
tree = parser.parse(text)
|
||||
tokens = FuncDefTransformer().transform(tree)
|
||||
assert len(tokens) == 3
|
||||
return tokens
|
||||
|
||||
def compile_func_header(func_def):
|
||||
func_name, params, retvals = func_def
|
||||
#print("Function:", func_name)
|
||||
#print("Params:", params)
|
||||
#print("Return values:", retvals)
|
||||
#print()
|
||||
|
||||
param_str = ""
|
||||
for param, type in params:
|
||||
if param_str:
|
||||
param_str += ", "
|
||||
param_str += param + ": Option<"
|
||||
if type == "U64":
|
||||
param_str += "u64"
|
||||
elif type == "Scalar":
|
||||
param_str += "jubjub::Fr"
|
||||
elif type == "Point":
|
||||
param_str += "jubjub::SubgroupPoint"
|
||||
else:
|
||||
print("error: unsupported param type", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
param_str += ">"
|
||||
|
||||
converted_retvals = []
|
||||
for type in retvals:
|
||||
if type == "Binary":
|
||||
converted_retvals.append("boolean::Boolean")
|
||||
else:
|
||||
print("error: unsupported return type", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
retvals = converted_retvals
|
||||
|
||||
if len(retvals) == 1:
|
||||
retstr = retvals[0]
|
||||
else:
|
||||
retstr = "(" + ", ".join(retvals) + ")"
|
||||
|
||||
header = r"""fn %s<CS>(
|
||||
mut cs: CS,
|
||||
%s
|
||||
) -> Result<%s, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<bls12_381::Scalar>,
|
||||
{
|
||||
""" % (func_name, param_str, retstr)
|
||||
return header
|
||||
|
||||
def as_expr(line, stack, consts, expr, code):
|
||||
var_from, type_to = expr.children
|
||||
if var_from not in stack:
|
||||
print("error: variable from not in stack frame:", var_from,
|
||||
file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
type_from = stack[var_from]
|
||||
|
||||
if type_from == "U64" and type_to == "Binary":
|
||||
code += "boolean::u64_into_boolean_vec_le(" + \
|
||||
"cs.namespace(|| \"" + line.text + "\"), " + var_from + \
|
||||
")?;"
|
||||
elif type_from == "Scalar" and type_to == "Binary":
|
||||
code += "boolean::field_into_boolean_vec_le(" + \
|
||||
"cs.namespace(|| \"" + line.text + "\"), " + var_from + \
|
||||
")?;"
|
||||
else:
|
||||
print("error: unknown type conversion!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
#print(var_from, type_from, type_to)
|
||||
return code, type_to
|
||||
|
||||
def mul_expr(line, stack, consts, expr, code):
|
||||
var_a, var_b = expr.children
|
||||
#print("MUL", var_a, var_b)
|
||||
|
||||
if var_b not in consts:
|
||||
print("error: unknown base!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
base_type = consts[var_b]
|
||||
if base_type != "Point":
|
||||
print("error: unknown base type!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
code += "ecc::fixed_base_multiplication(" + \
|
||||
"cs.namespace(|| \"" + line.text + "\"), &" + var_b + \
|
||||
", &" + var_a + ")?;"
|
||||
|
||||
return code, base_type
|
||||
|
||||
def add_expr(line, stack, consts, expr, code):
|
||||
var_a, var_b = expr.children
|
||||
|
||||
if var_a not in stack or var_b not in stack:
|
||||
print("error: missing stack item!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
result_type = stack[var_a]
|
||||
if stack[var_b] != result_type:
|
||||
print("error: non matching items for addition!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
code += var_a + ".add(cs.namespace(|| \"" + line.text \
|
||||
+ "\"), &" + var_b + ")?;"
|
||||
|
||||
return (code, result_type)
|
||||
|
||||
def compile_let(line, stack, consts, statement):
|
||||
is_mutable = False
|
||||
if statement[0] == "mut":
|
||||
is_mutable = True
|
||||
statement = statement[1:]
|
||||
variable_name, variable_type = statement[0], statement[1]
|
||||
expr = statement[2]
|
||||
#print("LET", is_mutable, variable_name, variable_type)
|
||||
#print(" ", expr)
|
||||
code = "let " + ("mut " if is_mutable else "") + variable_name + " = "
|
||||
|
||||
if expr.data == "as_expr":
|
||||
ceval = as_expr(line, stack, consts, expr, code)
|
||||
elif expr.data == "mul_expr":
|
||||
ceval = mul_expr(line, stack, consts, expr, code)
|
||||
elif expr.data == "add_expr":
|
||||
ceval = add_expr(line, stack, consts, expr, code)
|
||||
|
||||
if ceval is None:
|
||||
return None
|
||||
|
||||
code, type_to = ceval
|
||||
|
||||
if variable_type != type_to:
|
||||
print("error: sub expr does not evaluate to correct type",
|
||||
file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
stack[variable_name] = variable_type
|
||||
|
||||
return code
|
||||
|
||||
def interpret_func(func, consts):
|
||||
func_def = parse_func_def(func[0].text)
|
||||
|
||||
header = compile_func_header(func_def)
|
||||
if header is None:
|
||||
return
|
||||
|
||||
subroutine = header
|
||||
indent = " " * 4
|
||||
|
||||
stack = dict(func_def[1])
|
||||
emitted_types = []
|
||||
for line in func[1:]:
|
||||
statement_type, statement = interpret_func_line(line.text, stack, consts)
|
||||
if statement_type == "let":
|
||||
code = compile_let(line, stack, consts, statement)
|
||||
if code is None:
|
||||
return
|
||||
subroutine += indent + code + "\n"
|
||||
|
||||
elif statement_type == "return":
|
||||
for var in statement:
|
||||
if var not in stack:
|
||||
print("error: missing variable in stack!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
if len(statement) == 1:
|
||||
code = "Ok(" + statement[0] + ")"
|
||||
else:
|
||||
code = "Ok(" + ",".join(statement) + ")"
|
||||
subroutine += indent + code + "\n"
|
||||
|
||||
elif statement_type == "emit":
|
||||
assert len(statement) == 1
|
||||
variable = statement[0]
|
||||
if variable not in stack:
|
||||
print("error: missing variable in stack!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
variable_type = stack[variable]
|
||||
|
||||
if variable_type == "Point":
|
||||
code = variable + ".inputize(cs.namespace(|| \"" + \
|
||||
line.text + "\"))?;"
|
||||
else:
|
||||
print("error: unable to inputize type!", file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
emitted_types.append(variable_type)
|
||||
subroutine += indent + code + "\n"
|
||||
|
||||
subroutine += "}\n\n"
|
||||
return subroutine, emitted_types, func_def
|
||||
|
||||
class CodeLineTransformer(lark.Transformer):
|
||||
def variable_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def let_statement(self, obj):
|
||||
return ("let", obj)
|
||||
def return_statement(self, obj):
|
||||
return ("return", obj)
|
||||
def emit_statement(self, obj):
|
||||
return ("emit", obj)
|
||||
|
||||
def point(self, _):
|
||||
return "Point"
|
||||
def scalar(self, _):
|
||||
return "Scalar"
|
||||
def binary(self, _):
|
||||
return "Binary"
|
||||
def u64(self, _):
|
||||
return "U64"
|
||||
|
||||
def type(self, typename):
|
||||
return str(typename[0])
|
||||
|
||||
def mutable(self, _):
|
||||
return "mut"
|
||||
|
||||
statement = list
|
||||
|
||||
def interpret_func_line(text, stack, consts):
|
||||
parser = lark.Lark(r"""
|
||||
statement: let_statement
|
||||
| return_statement
|
||||
| emit_statement
|
||||
|
||||
let_statement: "let" [mutable] variable_name ":" type "=" expr
|
||||
mutable: "mut"
|
||||
|
||||
?expr: as_expr
|
||||
| mul_expr
|
||||
| add_expr
|
||||
|
||||
as_expr: variable_name "as" type
|
||||
mul_expr: variable_name "*" variable_name
|
||||
add_expr: variable_name "+" variable_name
|
||||
|
||||
return_statement: "return" variable_name
|
||||
| "return" variable_tuple
|
||||
variable_tuple: "(" variable_name ("," variable_name)* ")"
|
||||
|
||||
emit_statement: "emit" variable_name
|
||||
|
||||
variable_name: NAME
|
||||
type: u64 | scalar | point | binary
|
||||
|
||||
u64: "U64"
|
||||
scalar: "Scalar"
|
||||
point: "Point"
|
||||
binary: "Binary"
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
""", start="statement")
|
||||
tree = parser.parse(text)
|
||||
tokens = CodeLineTransformer().transform(tree)[0]
|
||||
return tokens
|
||||
|
||||
class ContractDefTransformer(lark.Transformer):
|
||||
def contract_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def param(self, obj):
|
||||
return tuple(obj)
|
||||
|
||||
def param_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def u64(self, _):
|
||||
return "U64"
|
||||
def scalar(self, _):
|
||||
return "Scalar"
|
||||
def point(self, _):
|
||||
return "Point"
|
||||
def binary(self, _):
|
||||
return "Binary"
|
||||
|
||||
def type(self, obj):
|
||||
return obj[0]
|
||||
|
||||
contract_def = list
|
||||
params = list
|
||||
type_list = list
|
||||
|
||||
def parse_contract_def(text):
|
||||
parser = lark.Lark(r"""
|
||||
contract_def: "contract" contract_name "(" params+ ")" "->" type_list ":"
|
||||
|
||||
contract_name: NAME
|
||||
params: param ("," param)*
|
||||
|
||||
type_list: type
|
||||
| "(" type ("," type)* ")"
|
||||
|
||||
param: param_name ":" type
|
||||
param_name: NAME
|
||||
|
||||
type: u64 | scalar | point | binary
|
||||
|
||||
u64: "U64"
|
||||
scalar: "Scalar"
|
||||
point: "Point"
|
||||
binary: "Binary"
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
""", start="contract_def")
|
||||
tree = parser.parse(text)
|
||||
tokens = ContractDefTransformer().transform(tree)
|
||||
assert len(tokens) == 3
|
||||
return tokens
|
||||
|
||||
class ContractCodeLineTransformer(lark.Transformer):
|
||||
def variable_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
def let_statement(self, obj):
|
||||
return ("let", obj)
|
||||
def return_statement(self, obj):
|
||||
return ("return", obj)
|
||||
def emit_statement(self, obj):
|
||||
return ("emit", obj)
|
||||
def method_statement(self, obj):
|
||||
return ("method", obj)
|
||||
|
||||
def point(self, _):
|
||||
return "Point"
|
||||
def scalar(self, _):
|
||||
return "Scalar"
|
||||
def binary(self, _):
|
||||
return "Binary"
|
||||
def u64(self, _):
|
||||
return "U64"
|
||||
|
||||
def type(self, typename):
|
||||
return str(typename[0])
|
||||
|
||||
def mutable(self, _):
|
||||
return "mut"
|
||||
|
||||
def function_name(self, name):
|
||||
return str(name[0])
|
||||
|
||||
statement = list
|
||||
variable_assign = list
|
||||
variable_decl = tuple
|
||||
|
||||
def interpret_contract_line(text, stack, consts):
|
||||
parser = lark.Lark(r"""
|
||||
statement: let_statement
|
||||
| return_statement
|
||||
| emit_statement
|
||||
| method_statement
|
||||
|
||||
let_statement: "let" variable_assign "=" expr
|
||||
mutable: "mut"
|
||||
|
||||
variable_assign: variable_decl
|
||||
| "(" variable_decl ("," variable_decl)* ")"
|
||||
variable_decl: [mutable] variable_name ":" type
|
||||
|
||||
?expr: as_expr
|
||||
| mul_expr
|
||||
| add_expr
|
||||
| funccall_expr
|
||||
| empty_list_expr
|
||||
|
||||
as_expr: variable_name "as" type
|
||||
mul_expr: variable_name "*" variable_name
|
||||
add_expr: variable_name "+" variable_name
|
||||
funccall_expr: function_name "(" [variable_name ("," variable_name)*] ")"
|
||||
empty_list_expr: "[]"
|
||||
|
||||
return_statement: "return" variable_name
|
||||
| "return" variable_tuple
|
||||
variable_tuple: "(" variable_name ("," variable_name)* ")"
|
||||
|
||||
emit_statement: "emit" variable_name
|
||||
|
||||
method_statement: variable_name "." funccall_expr
|
||||
|
||||
variable_name: NAME
|
||||
function_name: NAME
|
||||
type: u64 | scalar | point | binary
|
||||
|
||||
u64: "U64"
|
||||
scalar: "Scalar"
|
||||
point: "Point"
|
||||
binary: "Binary"
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
""", start="statement")
|
||||
tree = parser.parse(text)
|
||||
tokens = ContractCodeLineTransformer().transform(tree)[0]
|
||||
return tokens
|
||||
|
||||
def to_initial_caps(snake_str):
|
||||
components = snake_str.split("_")
|
||||
return "".join(x.title() for x in components)
|
||||
|
||||
def create_contract_header(contract_def):
|
||||
contract_name, params, retvals = contract_def
|
||||
contract_name = to_initial_caps(contract_name)
|
||||
|
||||
header = "pub struct %s {\n" % contract_name
|
||||
|
||||
for param_name, param_type in params:
|
||||
if param_type == "U64":
|
||||
param_type = "u64"
|
||||
elif param_type == "Scalar":
|
||||
param_type = "jubjub::Fr"
|
||||
elif param_type == "Point":
|
||||
param_type = "jubjub::SubgroupPoint"
|
||||
header += " " * 4 + "pub %s: Option<%s>,\n" % (param_name, param_type)
|
||||
|
||||
header += "}\n\n"
|
||||
|
||||
header += r"""impl Circuit<bls12_381::Scalar> for %s {
|
||||
fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
""" % contract_name
|
||||
|
||||
return header
|
||||
|
||||
# Worst code ever
|
||||
def compile_let2(line, stack, consts, funcs, selfvars, statement):
|
||||
lhs = []
|
||||
for variable_decl in statement[0]:
|
||||
assert len(variable_decl) == 2 or \
|
||||
(len(variable_decl) == 3 and variable_decl[0] == "mut")
|
||||
|
||||
if len(variable_decl) == 2:
|
||||
mutable = False
|
||||
elif len(variable_decl) == 3:
|
||||
assert variable_decl[0] == "mut"
|
||||
mutable = True
|
||||
variable_decl = variable_decl[1:]
|
||||
#else:
|
||||
# Error!
|
||||
|
||||
lhs.append(list(variable_decl) + [mutable])
|
||||
|
||||
variable_types = []
|
||||
|
||||
code = "let "
|
||||
if len(lhs) == 1:
|
||||
name, type, is_mutable = lhs[0]
|
||||
variable_types.append(type)
|
||||
code += ("mut " if is_mutable else "") + name
|
||||
else:
|
||||
code += "("
|
||||
start = True
|
||||
for name, type, is_mutable in lhs:
|
||||
if not start:
|
||||
code += ", "
|
||||
start = False
|
||||
|
||||
code += name
|
||||
|
||||
variable_types.append(type)
|
||||
code += ")"
|
||||
code += " = "
|
||||
|
||||
expr = statement[1]
|
||||
expr_type = expr.data
|
||||
expr = expr.children
|
||||
if expr_type == "funccall_expr":
|
||||
ceval = funccall_expr(line, stack, consts, funcs, selfvars, expr, code)
|
||||
elif expr_type == "empty_list_expr":
|
||||
ceval = code + "vec![];", ["Binary"]
|
||||
#code = "let " + ("mut " if is_mutable else "") + variable_name + " = "
|
||||
|
||||
if ceval is None:
|
||||
return None
|
||||
|
||||
code, types_to = ceval
|
||||
|
||||
if variable_types != types_to:
|
||||
print("error: sub expr does not evaluate to correct type",
|
||||
file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
for name, type, _ in lhs:
|
||||
stack[name] = type
|
||||
|
||||
return code
|
||||
|
||||
def funccall_expr(line, stack, consts, funcs, selfvars, expr, code):
|
||||
func_name, arguments = expr[0], expr[1:]
|
||||
|
||||
if func_name not in funcs:
|
||||
print("error: non-existant function call",
|
||||
file=sys.stderr)
|
||||
print("line:", line.text, "line:", line.lineno)
|
||||
return None
|
||||
|
||||
arguments = [("self." + arg if arg in selfvars else arg)
|
||||
for arg in arguments]
|
||||
|
||||
code += "%s(cs.namespace(|| \"%s\"), %s)?;" % (
|
||||
func_name, line.text, ", ".join(arguments))
|
||||
|
||||
return_type = funcs[func_name][-1][-1]
|
||||
return code, return_type
|
||||
|
||||
def compile_method_call(line, stack, consts, funcs, selfvars, statement):
|
||||
variable = statement[0]
|
||||
method = statement[1].children[0]
|
||||
arguments = statement[1].children[1:]
|
||||
|
||||
arguments = [("self." + arg if arg in selfvars else arg)
|
||||
for arg in arguments]
|
||||
|
||||
return "%s.%s(%s);" % (variable, method, ", ".join(arguments))
|
||||
|
||||
def interpret_contract(contract, consts, funcs):
|
||||
contract_def = parse_contract_def(contract[0].text)
|
||||
contract_code = create_contract_header(contract_def)
|
||||
|
||||
selfvars = set(varname[0] for varname in contract_def[1])
|
||||
stack = dict(contract_def[1])
|
||||
for line in contract[1:10]:
|
||||
indent = " " * 4 * int(line.level + 1)
|
||||
statement_type, statement = interpret_contract_line(line.text, stack, consts)
|
||||
#pprint.pprint(statement_type)
|
||||
if statement_type == "let":
|
||||
code = compile_let2(line, stack, consts, funcs, selfvars, statement)
|
||||
if code is None:
|
||||
return
|
||||
elif statement_type == "method":
|
||||
code = compile_method_call(line, stack, consts, funcs,
|
||||
selfvars, statement)
|
||||
if code is None:
|
||||
return
|
||||
|
||||
contract_code += indent + code + "\n"
|
||||
|
||||
contract_code += " " * 8 + "Ok(())\n"
|
||||
contract_code += " " * 4 + "}\n"
|
||||
contract_code += "}\n\n"
|
||||
|
||||
#print("-------------------------------")
|
||||
#print(contract_code)
|
||||
return contract_code, contract_def
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
print("error: missing proof file", file=sys.stderr)
|
||||
return -1
|
||||
filename = sys.argv[1]
|
||||
text = open(filename, "r").read()
|
||||
|
||||
if (linedescs := parse(text)) is None:
|
||||
return -1
|
||||
|
||||
sections = section(linedescs)
|
||||
|
||||
consts, funcs, contracts = classify(sections)
|
||||
|
||||
consts = read_consts(consts)
|
||||
|
||||
compiled_funcs = {}
|
||||
for func in funcs:
|
||||
if (compiled := interpret_func(func, consts)) is None:
|
||||
return -1
|
||||
|
||||
_, _, func_def = compiled
|
||||
func_name, _, _ = func_def
|
||||
|
||||
compiled_funcs[func_name] = compiled
|
||||
funcs = compiled_funcs
|
||||
|
||||
compiled_contracts = {}
|
||||
for contract in contracts[1:]:
|
||||
if (compiled := interpret_contract(contract, consts, funcs)) is None:
|
||||
return -1
|
||||
#print(contract)
|
||||
|
||||
_, contract_def = compiled
|
||||
contract_name, _, _ = contract_def
|
||||
|
||||
compiled_contracts[contract_name] = compiled
|
||||
contracts = compiled_contracts
|
||||
|
||||
# Concat
|
||||
output = ""
|
||||
for _, func in funcs.items():
|
||||
output += func[0]
|
||||
for _, contract in contracts.items():
|
||||
output += contract[0]
|
||||
|
||||
#print(output)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
[package]
|
||||
name = "pasta"
|
||||
version = "0.1.0"
|
||||
authors = ["narodnik <x@x.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
pasta_curves = { path = "/home/narodnik/src/sw/zectings/pasta_curves" }
|
||||
ff = "0.9"
|
||||
group = "0.9"
|
||||
rand = "0.8.4"
|
||||
|
||||
[[bin]]
|
||||
name = "pasta"
|
||||
path = "main.rs"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
use pasta_curves as pasta;
|
||||
use group::{Group, Curve};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
fn main() {
|
||||
let g = pasta::vesta::Point::generator();
|
||||
println!("G = {:?}", g.to_affine());
|
||||
let x = pasta::vesta::Scalar::from(87u64);
|
||||
println!("x = 87 = {:?}", x);
|
||||
let b = g * x;
|
||||
println!("B = xG = {:?}", b.to_affine());
|
||||
|
||||
let y = x - pasta::vesta::Scalar::from(90u64);
|
||||
println!("y = x - 90 = {:?}", y);
|
||||
|
||||
let c = pasta::vesta::Point::random(&mut OsRng);
|
||||
let d = pasta::vesta::Point::random(&mut OsRng);
|
||||
println!("C = {:?}", c.to_affine());
|
||||
println!("D = {:?}", d.to_affine());
|
||||
println!("C + D = {:?}", (c + d).to_affine());
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user