Commit ce39a68a authored by XFT-dev's avatar XFT-dev
Browse files

initializing repo

parent 8605a110
# protocol-main
offshift code + docs
\ No newline at end of file
# Confidential contracts ingredients
##
## 1. Homomorphic encryption
**Intro:**
Properties of the homomorphic encryption:
- The complexity of obtaining the original data from the ciphertext:
E(x) -> x.
- Changing the original data changes the outputs of the function:
If x != y ⇒ E(x) != E(y)
- With several known values of encrypted data, an arithmetic operation can be performed between them:
- If E(x) and E(y) are known, we can receive E(func(x + y)) without disclosure.
**Protocol:**
1. g - public generator;
2. Evaluation: E(x) = gx nod n;
3. E(x + y) = gx \* gy = E(x) \* E(y)
4. E(ax + by) = gax \* gby = E(x)a \* E(y)b
**Example:**
Consider an example that illustrates this approach. For example, Alice wants to prove to Bob that she knows two numbers, the sum of which will be 15. Take the values of the secrets x = 13 and y = 2. The parties jointly determine the modulus n = 17 and the base point value g = 3 (as the encryption algorithm we will use RSA). To prove to Bob that she knows these secrets, she blinds them and gets two meanings, which she gives to Bob:
E(x) = gx mod n=313 mod 17= 12mod 17,
E(y) = gy mod n=32mod 17=9 mod 17.
Bob, in turn, needs to make sure that the sum of the secrets is indeed equal to 15. To do this, he "adds" both values received from Alice as follows:
E(x + y) = gx+y mod n=gxgy mod n= 129 mod 17=6 mod 17.
Following this, he independently encrypts the known result 15 and compares the obtained values:
E(15) =g15 mod n=315 mod 17=6 mod 17=> E(x + y) = E(15).
Since the results are the same, Alice can prove to Bob that she knows two numbers that add up to 15, while not divulging these numbers, but only transmitting them in an encrypted (blinded) form. Therefore, the properties we noted earlier are fully secured.
##
## 2. Blind Evaluation of Polynomials
**Intro:**
The polynomial is represented as follows:
F(x)=a0+a1x + a2x2+...+an-1xn-1, where
x – variable, a – constant coefficients. We can evaluate a polynomial in terms of a specific value of s:
F(s)=a0+a1s + a2s2+...+an-1sn-1
Accordingly, the party who knows the coefficients of the polynomial can evaluate it at any point.
**Protocol** :
1. Bob sends to Alice E(1), E(s), …, E(sd);
2. Alice computes and returns E(P(s)).
**Example:**
So, suppose Bob knows a particular polynomial and wants to make sure that its coefficients are also known to Alice (who doesn't want to divulge them). To do this, he wants to get a blinded value E(P(x)) from Alice. If it weren't for zero knowledge proofs, Bob could have passed x to Alice and got P(x). However, what if Bob doesn't want to pass on the secret to Alice?
For this, homomorphic encryption, which we discussed earlier, can be used. Bob initially forms E(P(x)) and "memorizes" it in order to compare it with the value received from Alice. After that, he forms a set of blinded values of the polynomial components and passes them to Alice:
E(1), E(x), E(x2),...,E(xn-1).
Note that if at this stage Alice knows the coefficients of the polynomial, then she can provide the correct value for E(P(x)). How does this happen? We discussed earlier how the blinded value is multiplied by a scalar. Also, in this case, Alice can multiply the blinded values received from Bob by the coefficients she knows. As a result, it will receive the following value:
E(P(x)) =E(1)a0E(x)a1E(x2)a2...E(xn-1)an-1.
The resulting blinded value is passed to Bob and compared with the previously calculated one. If the values match, then Bob is guaranteed to make sure that Alice knows the coefficients of the polynomial (except for a very low probability). At the same time, everyone fulfills the properties of zero-knowledge proofs: Alice does not learn the secret from Bob, does not divulge the values of the coefficients to Bob, but convinces him that she knows these values.
## 3. Knowledge of the Coefficient
**Intro:**
In the example above, Alice does not have to send Bob the correct estimate of the polynomial - she can send him fake data (we are based on the assumption that Bob cannot estimate the polynomial on his own and check the result).
**Protocol:**
KC test proceeds as follows:
1. Bob chooses random α and a ∈ G snf computes b = αa.
2. Bob sends "challenge" α-pair (a, b). Alice can't receive the α value.
3. Alice sends different α-pair (a', b'). How she can successfully respond to the challenge without knowingα:
1. Alice chooses some γ and responds via (a', b') = (γa, γb). Alice knows the ration between a and a'.
4. If (a', b') is valid α-pair Bob accepts Alice's response.
**Example:**
For example, Bob generates a random value a = 3 and α = 7. He calculates b = αa = 3 \* 7 = 21. Bob sends to Alice 3 and 21. In this case, it is quite easy to find the value α = 7, however, due to the peculiarities of arithmetic, which we use, this solution is in the field of the solution to the discrete logarithm problem. Alice then chooses the value γ = 13 and calculates:
(a', b') = (γa, γb) = (13 \* 3, 13 \* 21) = (39, 273)
Alice then passes the α-pair to Bob. Bob's check is b'(273)? = αa'(7 \* 39). In this case, Bob can verify that (a', b') are an α-pair.
##
## 4. Verifiable blind evaluation of polynomials
**Intro:**
Now we turn to how the blinding of polynomials occurs so that Bob can verify that he received the correct evaluation from Alice. In this case, 2 properties must be fulfilled:
- Blindness (Alice will not receive the s);
- Verifiability (Alice can not provide fake value instead E(P(s))).
Bob sends several α-pairs (a0, b0),...,(an-1, bn-1). Alice has to return different α-pair (a', b'). (a', b') = (sum(ciai), sum(cibi)), ci are generated by Alice.
**Protocol:**
1. Bob chooses random α and sends to Alice hided values of:
1. 1, s, …, sd: E(1), E(s), …, E(sd);
2. α, αs, …, αsd: E(α), E(αs), …, E(αsd)
2. Alice computes a = E(P(s)) and b = αE(P(s))
3. Bob checks that b = αa.
## 5. Arithmetic circuits
**Intro:**
Everything that was described earlier is the mechanism of operation and calculation with polynomials. Now we need to figure out how to transform some statement (which needs to be proved and verified) into a set of polynomials.
An arithmetic circuit consists of gates computing arithmetic operations like addition and multiplication, with wires connecting the gates.
**Protocol:**
The complex program has to be divided to minimal atomic operations in following form:
a = b (op) c
**Example:**
x2-x-6=0
Can be transformed to the program:
![](assets/image5.png)
That has to be divided to operations:
![](assets/image12.png)
## 6. R1CS
**Intro:**
Now we can convert the received states (simplified version of the code) to R1CS. To do this, first we need to form a state vector, which contains all the variables of the simplified program and the value 1 (to represent constant values).
![](assets/image1.png)
**Protocol:**
In fact, R1CS is a list of vector triplets (a, b, c) for which the following condition is satisfied:
<ai · s> <bi · s> - <ci · s> = 0
This equality must be fulfilled for each line of simplified code, that weis, the correspondence of each logical transition to a new state is controlled.
As a result we will receive the set of vectors a, b and c for each state of program like:
![](assets/image7.png)
**Example:**
1.
![](assets/image13.png)
![](assets/image8.png)
2 and 3.
![](assets/image11.png) ![](assets/image10.png)
![](assets/image4.png)
## 7. QAP
**Intro:**
To perform the transition to QAP, it is necessary to transform the set of vectors into a set of polynomials A, B and C. From three groups, each of which contains 3 vectors, we should get 15 polynomials of the third degree. To obtain a polynomial, we need to determine the points through which the graph described by this polynomial passes. Further, using these points and Lagrange interpolation, we get polynomials.
**Protocol:**
When using Lagrange interpolation, the polynomial is calculated as follows:
L(x)=i=0nfi(x)li(x), where li(x)=j=0, jinx - xjxi-xj.
**Example:**
![](assets/image3.png)
Further, based on the obtained values of the points, we transform the vectors into the following set of polynomials:
![](assets/image6.png)
We can check the polynomial&#39;s correctness next way:
![](assets/image14.png)
Transformation into QAP allows us to transform equality into an equality of the following type:
A(x)*B(x)-C(x)=0, where
A(x) = A · s, B(x) = B · s, C(x) = C · s.
This equality will be fulfilled for each transition (x = 1, 2, 3). However, in doing so, we can check the compliance of our witness with this task. If we change the value of witness, for example, instead of [1, 3, 9, 6, 0] we take [1, 3, 10, 6, 0], then the equality for the transitions will not be fulfilled:
![](assets/image2.png)
In this case, we get a lot of term, which must be divisible without a remainder by (x-1)(x-2)(x-3), since 1, 2 and 3 are its roots (the function will take on the value 0). That is, we can quickly check the validity of a polynomial by dividing by said polynomial:
L(x) = (x-1)(x-2)(x-3)\*H(x), where (x-1)(x-2)(x-3) = T(x)
## 8. Pinocchio protocol
**Intro:**
The prover can send the verifier a short proof that she has the required QAP assignment set.
**Protocol:**
1. Alice select A(x), B(x), C(x) and H(x);
2. Bob selects random r and computes E(T(x));
3. Alice sends to Bob E(A(x)), E(B(x)), E(C(x)), E(H(x));
4. Bob checks E(A(x)\*B(x)-C(x)) == E(T(x)\*H(x)).
The protocol above only guarantees that Alice uses some polynomials of the correct order, but does not guarantee that they were created from a valid assignment set. The formal proof is somewhat tricky, so we will give an example solution.
##
## 9. Zcash shielding
Commitment = Hash(recipient address, amount, rho, r):
- rho - unique value used for nullifier derivation;
- R - random nonce.
During shielded transaction spending sender uses spending key
Nullifier = Hash(spending key, rho).
## ![](assets/image9.png)
## 10. Elliptic curve pairing
**Intro:**
I think for now we can omit how it works.
## 11. ZOKRATES Example
**docker run -ti zokrates/zokrates /bin/bash**
**cd home**
**cd zokrates**
**mkdir test**
**touch root.zok**
**cat \&gt; root.zok**
## 11.1 Problem
Lets prove that we know some _ **a** _-value that a^2 == b.
## 11.2 Problem description
def main(private field a, field b) -\&gt; bool: **// program on zokrates language**
return a\*a == b
## 11.3 From problem to arithmetic circuits
**zokrates compile -i root.zok**
Compiled program: **// initial C program (arithmetic circuit)**
def main(\_0, \_1) -\&gt; (1):
(1 \* \_0) \* (1 \* \_0) == 1 \* \_4
# \_2, \_3 = ConditionEq((1 \* ~one) \* ((-1) \* \_1 + 1 \* \_4))
((-1) \* \_1 + 1 \* \_4) \* (1 \* \_3) == 1 \* \_2
(1 \* ~one + (-1) \* \_2) \* ((-1) \* \_1 + 1 \* \_4) == 0
(1 \* ~one) \* (1 \* ~one + (-1) \* \_2) == 1 \* ~out\_0
return ~out\_0
Compiled code written to &#39;out&#39;
Human readable code to &#39;out.ztf&#39;
Number of constraints: 4
**ls**
abi.json out out.ztf root.zok
**cat out //displaying in compiled form**
ZOK????mai???C?p?yH?3(]X???EP?)?1?rNd???C?p?yH?3(]X???EP?)?1?rNd???C?p?yH?3(]X???EP?)?1?rNd???C?p?yH?3(]X???EP?)?1?rNd???C?p?yH?3(]X???EP?)?1?rNd0????????????????
**cat out.ztf**
def main(\_0, \_1) -\&gt; (1):
(1 \* \_0) \* (1 \* \_0) == 1 \* \_4
# \_2, \_3 = ConditionEq((1 \* ~one) \* ((-1) \* \_1 + 1 \* \_4))
((-1) \* \_1 + 1 \* \_4) \* (1 \* \_3) == 1 \* \_2
(1 \* ~one + (-1) \* \_2) \* ((-1) \* \_1 + 1 \* \_4) == 0
(1 \* ~one) \* (1 \* ~one + (-1) \* \_2) == 1 \* ~out\_0
return ~out\_0
**cat abi.json //binary interface**
{
&quot;inputs&quot;: [
{
&quot;name&quot;: &quot;a&quot;,
&quot;public&quot;: false,
&quot;type&quot;: &quot;field&quot;
},
{
&quot;name&quot;: &quot;b&quot;,
&quot;public&quot;: true,
&quot;type&quot;: &quot;field&quot;
}
],
&quot;outputs&quot;: [
{
&quot;type&quot;: &quot;bool&quot;
}
]
## 11.4 Trusted setup (prover and verifier keys generation)
**zokrates setup**
Performing setup...
def main(\_0, \_1) -\&gt; (1):
(1 \* \_0) \* (1 \* \_0) == 1 \* \_4
# \_2, \_3 = ConditionEq((1 \* ~one) \* ((-1) \* \_1 + 1 \* \_4))
((-1) \* \_1 + 1 \* \_4) \* (1 \* \_3) == 1 \* \_2
(1 \* ~one + (-1) \* \_2) \* ((-1) \* \_1 + 1 \* \_4) == 0
(1 \* ~one) \* (1 \* ~one + (-1) \* \_2) == 1 \* ~out\_0
return ~out\_0
WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving\_schemes.html#g16-malleability for implications.
| **NOTE**** When using G16, developers should pay attention to the fact that an attacker, seeing a valid proof, can very easily generate a different but still valid proof. Therefore, depending on the use case, making sure on chain that the same proof cannot be submitted twice may not be enough to guarantee that attackers cannot replay proofs. Mechanisms to solve this issue include:**
- **signed proofs**
- **nullifiers**
- **usage of an ethereum address as a public input to the program**
- **usage of non-malleable schemes such as GM17**
|
| --- |
From this reason we will use gm17 prove scheme
**zokrates setup -s gm17 -b ark //GM17 - prove scheme, ARK - backend (for GM17 supporting)**
Performing setup...
def main(\_0, \_1) -\&gt; (1):
(1 \* \_0) \* (1 \* \_0) == 1 \* \_4
# \_2, \_3 = ConditionEq((1 \* ~one) \* ((-1) \* \_1 + 1 \* \_4))
((-1) \* \_1 + 1 \* \_4) \* (1 \* \_3) == 1 \* \_2
(1 \* ~one + (-1) \* \_2) \* ((-1) \* \_1 + 1 \* \_4) == 0
(1 \* ~one) \* (1 \* ~one + (-1) \* \_2) == 1 \* ~out\_0
return ~out\_0
Setup completed.
I recommend not try to understand what is keeped in verifier key)
**cat verification.key**
{
&quot;h&quot;: [
[
&quot;0x21ed25b314584c89fd75fc60b48ae3c5862a6fecb1ce467d6c6de3816fb2b7df&quot;,
&quot;0x3032b7523599019887d7967dc5c5b6db702b89d8af9a7b09bfa6ca8575cdac56&quot;
],
[
&quot;0x17d27e70aca2e4402b4d3c5d0b4fa42fe861ff09e6452cf6a30340d3b831b187&quot;,
&quot;0x173b7f0b011769371695d87258a9794cf5ef6a210025b2ef8d0adc4a19b23af0&quot;
]
],
&quot;g\_alpha&quot;: [
&quot;0x278a9668fe236f39390edf6e1a549f824eaae03635cabefdb4d503f5826513d2&quot;,
&quot;0x0ae043095f676b9ef74237fdaf4d3002403c328d55d1763d3905d2ddf763b55d&quot;
],
&quot;h\_beta&quot;: [
[
&quot;0x02b8284a22bbfa1f969b47f9063b5fc326c9ba46da517ada70a27aafd9a7a592&quot;,
&quot;0x10a859399627a97eefa078cf7120a0917f095ac4b865434fb6fa33472bc3d59d&quot;
],
[
&quot;0x22679a7aedbf02a36bf41265ed6673f3a8a55f4b49966bf325175da5c837e262&quot;,
&quot;0x01b24384861ffee62a56edd0210072ef823b9609df3cbce84f6c146531f5b216&quot;
]
],
&quot;g\_gamma&quot;: [
&quot;0x29c9815e24bcbe89fcdfe9f1b2dc3dbd80b3e3a9d5a49dee883f476ae9aa711f&quot;,
&quot;0x063b306c1e6dfb31a84a1ac01f869f6350ff743a7d64a27a9c266038395018c9&quot;
],
&quot;h\_gamma&quot;: [
[
&quot;0x21ed25b314584c89fd75fc60b48ae3c5862a6fecb1ce467d6c6de3816fb2b7df&quot;,
&quot;0x3032b7523599019887d7967dc5c5b6db702b89d8af9a7b09bfa6ca8575cdac56&quot;
],
[
&quot;0x17d27e70aca2e4402b4d3c5d0b4fa42fe861ff09e6452cf6a30340d3b831b187&quot;,
&quot;0x173b7f0b011769371695d87258a9794cf5ef6a210025b2ef8d0adc4a19b23af0&quot;
]
],
&quot;query&quot;: [
[
&quot;0x12cfe3e37bc89a4ced92c48be1745973a011be6fc0a01afee6fc8100ba40329d&quot;,
&quot;0x0d6ebd5b8ce577577c8ef036f1d737e7be647b948dfdfd7b47707981d1629cd3&quot;
],
[
&quot;0x2347a9ab877444c1b5b5474d572c793f6318f0f25ea0433d22e7b49a7316e004&quot;,
&quot;0x1b1fd6f7178b50033301608a01e55c67bda52546a03d4215a472e1b41a4a59dc&quot;
],
[
&quot;0x03ff7e4173415786c57995ac258ef71181f1905802abf12b80280a6d31f1b426&quot;,
&quot;0x0731ee572bd61e233d0081fc15b34f2e345263e29fed957a11277d6013407d5d&quot;
]
]
## 11.5 Witness computation
**zokrates compute-witness -a 7 5 // 337^2 == 113569**
Computing witness...
def main(\_0, \_1) -\&gt; (1):
(1 \* \_0) \* (1 \* \_0) == 1 \* \_4
# \_2, \_3 = ConditionEq((1 \* ~one) \* ((-1) \* \_1 + 1 \* \_4))
((-1) \* \_1 + 1 \* \_4) \* (1 \* \_3) == 1 \* \_2
(1 \* ~one + (-1) \* \_2) \* ((-1) \* \_1 + 1 \* \_4) == 0
(1 \* ~one) \* (1 \* ~one + (-1) \* \_2) == 1 \* ~out\_0
return ~out\_0
Witness:
[&quot;1&quot;]
**cat witness**
~out\_0 1
~one 1
\_0 337
\_1 113569
\_2 0
\_3 1
\_4 113569
## 11.6 Proofs computation
**zokrates generate-proof -s gm17 -b ark**
Generating proof...
Proof:
{
&quot;proof&quot;: {
&quot;a&quot;: [
&quot;0x1e605fe761bd55b5f1553338e912bf8c5a6f74c67a867ee22ebe1313809a6d6f&quot;,
&quot;0x05c3bbade2ba5783c8dc23fe195dea1c38fed05917aedd2e7535bc3665d027a4&quot;
],
&quot;b&quot;: [
[
&quot;0x304ac962dc4f96c5dd3124264657069b1639ca44e8a4fba64e47b33fc3c76e88&quot;,
&quot;0x2ddddfd5a1c9ea0f92d4568fbfd07495525892217bf7680a4bfbe6019e36991b&quot;
],
[
&quot;0x18cb37a3b678cb3cb80e3d6cec5aa3a72afb581b6a60c6a12b24afe2bb631213&quot;,
&quot;0x11f7855f453796b83d7910c2cacb33c6f4804914e16b90131caa7e88246b55d8&quot;
]
],
&quot;c&quot;: [
&quot;0x199eb31e71ef8a06b5837a2296bc61adfdf95e7f537c6947f4ca43fff2e0c2f8&quot;,
&quot;0x2491f520d3cd4b8cb96fec337ae5ea08ffb567383b5fda22dab0b59b7c82d84d&quot;
]
},