diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic
index 281fc2fb13..d145a4877e 100644
--- a/.config/dictionaries/project.dic
+++ b/.config/dictionaries/project.dic
@@ -43,6 +43,7 @@ Chotivichit
chromedriver
chrono
ciphertext
+ciphertexts
CIPs
COCOAPODS
codegen
diff --git a/docs/src/architecture/08_concepts/voting_transaction/crypto.md b/docs/src/architecture/08_concepts/voting_transaction/crypto.md
index 5ae02eeaa1..0b4db24a3f 100644
--- a/docs/src/architecture/08_concepts/voting_transaction/crypto.md
+++ b/docs/src/architecture/08_concepts/voting_transaction/crypto.md
@@ -49,7 +49,7 @@ The protocol is based around the following entities:
Or it could be defined based on their stake in the blockchain,
which is more appropriate for web3 systems.
-Important to note that the protocol defined for some **one** proposal.
+Important to note that the protocol defined for **single** proposal.
Obviously, it could be easily scaled for a set of proposals,
performing protocol steps in parallel.
@@ -86,14 +86,14 @@ the length of such vector **must** be equal to the amount of the voting options
$i$ corresponds to the proposal voting choice and
defines that the $i$-th component of the unit vector equals to $1$
and the rest components are equals to $0$.
-And it stands as an identifier of the unit vector and could varies $1 \le i \le M$,
+And it stands as an identifier of the unit vector and could varies $0 \le i \le M - 1$,
$M$ - amount of the voting options.
E.g. proposal has voting options $[Yes, No, Abstain]$:
-* $\mathbf{e}_1$ equals to $(1,0,0)$ corresponds to $Yes$
-* $\mathbf{e}_2$ equals to $(0,1,0)$ corresponds to $No$
-* $\mathbf{e}_3$ equals to $(0,0,1)$ corresponds to $Abstain$
+* $\mathbf{e}_0$ equals to $(1,0,0)$ corresponds to $Yes$
+* $\mathbf{e}_1$ equals to $(0,1,0)$ corresponds to $No$
+* $\mathbf{e}_2$ equals to $(0,0,1)$ corresponds to $Abstain$
Lets $e_{i,j}$ denote as an each component value of the unit vector $\mathbf{e}_i$.
Where $i$ is a unit vector's identifier as it was described before,
@@ -103,35 +103,36 @@ $M$ - amount of the voting options and equals to the length of the unit vector.
Using such notation unit vector $\mathbf{e}_i$ could be defined as
\begin{equation}
-\mathbf{e}_i = (e_{i,1}, \ldots, e_{i,M})
+\mathbf{e}_i = [e_{i,0}, \ldots, e_{i,M - 1}]
\end{equation}
E.g. for the unit vector
-$\mathbf{e}_1 = (1,0,0)$
+$\mathbf{e}_0 = [1,0,0]$
components would be defined as follows:
-* $e_{1, 1}$ equals to $1$
-* $e_{1, 2}$ equals to $0$
-* $e_{1, 3}$ equals to $0$
+* $e_{0, 0}$ equals to $1$
+* $e_{0, 1}$ equals to $0$
+* $e_{0, 2}$ equals to $0$
-#### Vote encrypting
+#### Vote encryption
After the choice is done (described in [section](#voting-choice)),
vote **must** be encrypted using shared election public key $pk$.
-To achieve that, Lifted ElGamal encryption algorithm is used,
-noted as $ElGamalEnc(message, randomness, public \; key)$.
+To achieve that, Lifted ElGamal encryption algorithm is used `ElGamalEnc`,
+noted as $VoteEnc(message, randomness, public \; key)$.
More detailed description of the lifted ElGamal algorithm
you can find in the [appendix B](#b-lifted-elgamal-encryptiondecryption).
-$ElGamalEnc(message, randomness, public \; key)$ algorithm produces a ciphertext $c$ as a result.
+$VoteEnc(message, randomness, public \; key)$ algorithm produces
+a ciphertext $c$ with the generated randomness $r$ as a result.
\begin{equation}
-c = ElGamalEnc(message, randomness, public \; key)
+c, r = VoteEnc(message, public \; key)
\end{equation}
To encrypt previously generated unit vector $\mathbf{e}_i$ ($i$ - voting choice identifier),
@@ -143,7 +144,7 @@ where $j$ is the same vector component's index $j$ value, $e_{i, j} => r_j$.
Then, for each vector component $e_{i,j}$ with the corresponding randomness $r_j$,
perform encryption algorithm applying shared election public key $pk$.
\begin{equation}
-c_j = ElGamalEnc(e_{i,j}, r_j, pk)
+c_j, r_j = VoteEnc(e_{i,j}, pk)
\end{equation}
As a result getting a vector $\mathbf{c}$ of ciphertext values $c_f$,
@@ -151,7 +152,7 @@ with the size equals of the size $\mathbf{e}_t$ unit vector,
equals to the amount of the voting options.
Lets denote this vector as:
\begin{equation}
-\mathbf{c} = (c_1, \ldots, c_{M}) = (ElGamalEnc(e_{i,j}, r_j, pk), \ldots, ElGamalEnc(e_{i,M}, r_M, pk))
+\mathbf{c}, \mathbf{r} = [(c_0, r_0), \ldots, (c_{M-1}, r_{M-1})] = (VoteEnc(e_{i,j}, pk), \ldots, VoteEnc(e_{i,M - 1}, pk))
\end{equation}
where $M$ is the voting options amount and $i$ is the index of the voting choice.
@@ -163,11 +164,11 @@ This is a first part of the published vote for a specific proposal.
#### Voter's proof
After the voter's choice is generated and encrypted,
-it is crucial to prove that [encoding](#voting-choice) and [encryption](#vote-encrypting) are formed correctly
+it is crucial to prove that [encoding](#voting-choice) and [encryption](#vote-encryption) are formed correctly
(i.e. that the voter indeed encrypt a unit vector).
-Because by the definition of the encryption algorithm $ElGamalEnc(message, randomness, public \; key)$
-it is possible to encrypt an any message value,
+Because by the definition of the encryption algorithm $VoteEnc(message, public \; key)$
+encrypts any message value,
it is not restricted for encryption only $0$ and $1$ values
(as it was stated in the previous [section](#voting-choice),
unit vector components only could be $0$ or $1$).
@@ -180,7 +181,7 @@ noted as $VoteProof(\mathbf{c}, \mathbf{e}_i, \mathbf{r}, pk)$.
It takes an encrypted vote vector $\mathbf{c}$,
an original vote unit vector $\mathbf{e}_i$,
a randomness vector $\mathbf{r}$,
-which was used during encryption algorithm $ElGamalEnc$
+which was used during encryption algorithm $VoteEnc$
and an shared election public key $pk$.
As a result it generates a proof value $\pi$.
\begin{equation}
@@ -419,13 +420,24 @@ Tally(i, [\mathbf{c_1}, \mathbf{c_2}, \ldots, \mathbf{c_N}], [\alpha_1, \alpha_2
\end{equation}
Where $c_{j, i}$ - an encrypted corresponded $i$-th vector's component of the encrypted vote $\mathbf{c_j}$.
-As it was stated in this [section](#vote-encrypting) each encrypted vote is a vector
+As it was stated in this [section](#vote-encryption) each encrypted vote is a vector
$\mathbf{c_j} = (c_{j, 1}, \ldots, c_{j, M})$, $M$ - number of voting choices.
$er_i$ noted as encrypted tally result for the provided $i$-th voting choice.
As it is not an open decrypted value yet,
it needs a decryption procedure corresponded for which encryption one was made.
+Important to note that the resulted value $er_i$ is a ciphertext, the same as $c_{j, i}$.
+So $er_i = (er_{i, 1}, er_{i, 2})$ consists of elements $er_{i, 1}, er_{i, 2} \in \mathbb{G}$.
+Operations which are applied for pair $c_{j, i} \circ c_{j+1, i}$, actually means the following:
+
+\begin{equation}
+c_{j, i} \circ c_{j+1, i} = (c_{j, i, 1} \circ c_{j+1, i, 1},\quad c_{j, i, 2} \circ c_{j+1, i, 2})
+\end{equation}
+
+So $\circ$ operation applied separately for each corresponding items of the ciphertexts $c_{j, i}, c_{j+1, i}$
+and in the result we are getting a new ciphertext.
+
## D: Non-Interactive ZK Vote Proof
@@ -456,7 +468,7 @@ The prover algorithm takes as arguments:
So basically here is the relation between all these values:
\begin{equation}
-\mathbf{c} = (c_1, \ldots, c_M) = (ElGamalEnc(e_{i,1}, r_1, pk), \ldots, ElGamalEnc(e_{i,M}, r_M, pk))
+\mathbf{c} = (c_1, \ldots, c_M) = (VoteEnc(e_{i,1}, r_1, pk), \ldots, VoteEnc(e_{i,M}, r_M, pk))
\end{equation}
\begin{equation}
@@ -470,15 +482,15 @@ $\pi$ is the final proof.
To compute it, prover needs to perform the next steps:
1. If the number of voting options $M$ is not a perfect power of $2$,
- extend the vector $\mathbf{c}$ with $c_j = ElGamalEnc(0, 0, pk)$,
+ extend the vector $\mathbf{c}$ with $c_j = VoteEnc(0, 0, pk)$,
where $N$ is a perfect power of $2$, $j \in [M, \ldots, N - 1]$.
So the resulted $\mathbf{c} = (c_1, \ldots, c_M, \{c_j\})$.
2. Generate a commitment key $ck \in \mathbb{G}$.
-3. Let $i_k$ is a bit value of the $i$-th binary representation,
+3. Let $i_k$ is a bit value of the $i$-th binary representation (little-endian order),
where $k \in [0, log_2(N) - 1]$.
E.g. $i=3$ and $N=8, log_2(N) = 3$,
its binary representation $i=011$,
- $i_0=0, i_1=1, i_2=1$.
+ $i_0=1, i_1=1, i_2=0$.
4. For $l \in [0, \ldots, log_2(N)-1]$ generate a random values
$\alpha_l, \beta_l, \gamma_l, \delta_l, \in \mathbb{Z}_q$.
5. For $l \in [0, \ldots, log_2(N)-1]$ calculate, where $g$ is the group generator:
@@ -486,7 +498,7 @@ To compute it, prover needs to perform the next steps:
* $B_l = g^{\beta_l} \circ ck^{\gamma_l}, B_l \in \mathbb{G}$.
* $A_l = g^{i_l * \beta_l} \circ ck^{\delta_l}, A_l \in \mathbb{G}$.
6. Calculate a first verifier challenge
- $com_1 = H(ck, pk, \{c_j\}, \{I_l\}, \{B_l\}, \{A_l\})$,
+ $ch_1 = H(ck, pk, \{c_j\}, \{I_l\}, \{B_l\}, \{A_l\})$,
where $H$ is a hash function,
$j \in [0, \ldots, N-1]$
and $l \in [0, \ldots, log_2(N)-1]$.
@@ -498,19 +510,19 @@ To compute it, prover needs to perform the next steps:
* Calculate the polynomial itself $p_j(x) = \prod_{l=0}^{log_2(N)-1} z_l^{j_l}$
8. For $l \in [0, \ldots, log_2(N)-1]$ generate a random $R_l \in \mathbb{Z}_q$.
9. For $l \in [0, \ldots, log_2(N)-1]$ compute
- $D_l = ElGamalEnc(sum_l, R_l, pk)$,
- where $sum_l = \sum_{j=0}^{N-1}(p_{j,l} * com_1^j)$
+ $D_l = VoteEnc(sum_l, R_l, pk)$,
+ where $sum_l = \sum_{j=0}^{N-1}(p_{j,l} * ch_1^j)$
and $p_{j,l}$ - corresponding coefficients of the polynomial $p_j(x)$ calculated on step `7`.
10. Calculate a second verifier challenge
- $com_2 = H(com_1, \{D_l\})$,
+ $ch_2 = H(ch_1, \{D_l\})$,
where $H$ is a hash function
and $l \in [0, \ldots, log_2(N)-1]$.
11. For $l \in [0, \ldots, log_2(N)-1]$ calculate:
- * $z_l = i_l * com_2 + \beta_l, z_l \in \mathbb{Z}_q$.
- * $w_l = \alpha_l * com_2 + \gamma_l, w_l \in \mathbb{Z}_q$.
- * $v_l = \alpha_l * (com_2 - z_l) + \delta_l, v_l \in \mathbb{Z}_q$.
+ * $z_l = i_l * ch_2 + \beta_l, z_l \in \mathbb{Z}_q$.
+ * $w_l = \alpha_l * ch_2 + \gamma_l, w_l \in \mathbb{Z}_q$.
+ * $v_l = \alpha_l * (ch_2 - z_l) + \delta_l, v_l \in \mathbb{Z}_q$.
12. Calculate
- $R=\sum_{j=0}^{N-1}(r_j * (com_2)^{log_2(N)} * (com_1)^j) + \sum_{l=0}^{log_2(N)-1}(R_l * (com_2)^l)$,
+ $R=\sum_{j=0}^{N-1}(r_j * (ch_2)^{log_2(N)} * (ch_1)^j) + \sum_{l=0}^{log_2(N)-1}(R_l * (ch_2)^l)$,
where $r_j$ original random values which was used to encrypt $c_j$
and $R_l$ random values generated in step `8`.
@@ -537,42 +549,42 @@ Knowing that $\pi$ equals to $(ck, \{I_l\}, \{B_l\}, \{A_l\}, \{D_l\}, \{z_l\},
verifier needs to perform the next steps:
1. If the number of voting options $M$ is not a perfect power of $2$,
- extend the vector $\mathbf{c}$ with $c_j = ElGamalEnc(0, 0, pk)$,
+ extend the vector $\mathbf{c}$ with $c_j = VoteEnc(0, 0, pk)$,
where $N$ is a perfect power of $2$, $j \in [M, \ldots, N - 1]$.
So the resulted $\mathbf{c} = (c_1, \ldots, c_M, \{c_j\})$.
2. Calculate the first verifier challenge
- $com_1 = H(ck, pk, \{c_j\}, \{I_l\}, \{B_l\}, \{A_l\})$,
+ $ch_1 = H(ck, pk, \{c_j\}, \{I_l\}, \{B_l\}, \{A_l\})$,
where $H$ is a hash function,
$j \in [0, \ldots, N-1]$
and $l \in [0, \ldots, log_2(N)-1]$.
3. Calculate a second verifier challenge
- $com_2 = H(com_1, \{D_l\})$,
+ $ch_2 = H(ch_1, \{D_l\})$,
where $H$ is a hash function
and $l \in [0, \ldots, log_2(N)-1]$.
4. For $l \in [0, \ldots, log_2(N)-1]$ verify that the following statements are `true`,
where $g$ is the group generator:
- * $(I_l)^{com_2} \circ B_l == g^{z_l} \circ ck^{w_l}$.
- * $(I_l)^{com_2 - z_l} \circ A_l == g^{0} \circ ck^{v_l}$.
-5. Calculate the following $Left = ElGamalEnc(0, R, pk)$.
+ * $(I_l)^{ch_2} \circ B_l == g^{z_l} \circ ck^{w_l}$.
+ * $(I_l)^{ch_2 - z_l} \circ A_l == g^{0} \circ ck^{v_l}$.
+5. Calculate the following $Left = VoteEnc(0, R, pk)$.
Note that the $Left$ is a ciphertext, $Left = (Left_1, Left_2)$.
6. Note that $D_l$ is a ciphertext,
$D_l = (D_{l,1}, D_{l,2})$, for $l \in [0, \ldots, log_2(N)-1]$
calculate the following:
- * $Right2_1 = (D_{0,1})^{0} \circ \ldots \circ (D_{log_2(N) - 1,1})^{log_2(N) - 1}$.
- * $Right2_2 = (D_{0,2})^{0} \circ \ldots \circ (D_{log_2(N) - 1,2})^{log_2(N) - 1}$.
-7. For $j \in [0, \ldots, N-1]$ calculate the $p_j(com_2)$,
+ * $Right2_1 = (D_{0,1})^{ch_2^{0}} \circ \ldots \circ (D_{log_2(N) - 1,1})^{ch_2^{log_2(N) - 1}}$.
+ * $Right2_2 = (D_{0,2})^{ch_2^{0}} \circ \ldots \circ (D_{log_2(N) - 1,2})^{ch_2^{log_2(N) - 1}}$.
+7. For $j \in [0, \ldots, N-1]$ calculate the $p_j(ch_2)$,
where $p_j$ is a prover's defined polynomial defined in step `7`:
* $j_l$ is a bit value of the $j$-th binary representation.
* $z_l^1 = z_j$.
- * $z_l^0 = com_2 - z_j^1$.
- * $p_j(com_2) = \prod_l^{log_2(N)-1} z_l^{j_l}$.
-8. For $j \in [0, \ldots, N-1]$ calculate the $P_j = ElGamalEnc(-p_j(com_2), 0, pk)$.
+ * $z_l^0 = ch_2 - z_j^1$.
+ * $p_j(ch_2) = \prod_l^{log_2(N)-1} z_l^{j_l}$.
+8. For $j \in [0, \ldots, N-1]$ calculate the $P_j = VoteEnc(-p_j(ch_2), 0, pk)$.
Note that the $P_j$ is a ciphertext, $P_j = (P_{j,1}, P_{j,2})$.
9. Note that $C_j$ is a ciphertext,
$C_j = (C_{j,1}, C_{j,2})$, for $j \in [0, \ldots, N-1]$
calculate:
- * $Right1_{j,1} = (C_{j,1})^{com_2^{log_2(N)}} \circ (P_{j,1})^{com_1^{j}}$.
- * $Right1_{j,2} = (C_{j,2})^{com_2^{log_2(N)}} \circ (P_{j,2})^{com_1^{j}}$.
+ * $Right1_{j,1} = (C_{j,1})^{ch_2^{log_2(N)}} \circ (P_{j,1})^{ch_1^{j}}$.
+ * $Right1_{j,2} = (C_{j,2})^{ch_2^{log_2(N)}} \circ (P_{j,2})^{ch_1^{j}}$.
* $Right1_{1} = Right1_{j,1} \circ \ldots \circ Right1_{N - 1, 1}$.
* $Right1_{2} = Right1_{j,2} \circ \ldots \circ Right1_{N - 1, 2}$.
10. Verify that the following statements are `true`:
@@ -589,8 +601,8 @@ using exactly that secret key,
which is corresponds to the some shared public key.
-A more detailed and formal description
-you can find in the sections *Fig. 10* and *2.1.5* of this [paper][treasury_system_spec].
+It is a slightly modified version of the algorithm described in the sections
+*Fig. 10* and *2.1.5* of this [paper][treasury_system_spec].
It is assumed that the original encryption and decryption is performing by ElGamal scheme.
@@ -611,16 +623,16 @@ TallyProof(enc, sk) = \pi
$\pi$ is the final proof.
To compute it, prover needs to perform the next steps:
-1. Take the first element of the ciphertext $enc = (enc_1, enc_2)$
- and calculate $d = enc_1^{sk}$.
-2. Generate a random value $\mu, \quad \mu \in \mathbb{Z}_q$.
-3. Compute $A_1 = g^{\mu}$, where $g$ is the group generator ($A_1 \in \mathbb{G}$).
-4. Compute $A_2 = (enc_1)^{\mu}, \quad A_2 \in \mathbb{G}$.
-5. Compute $e = H(pk, d, g, enc_1, A_1, A_2 )$,
+1. Take the first element of the ciphertext $enc = (enc_1, enc_2)$.
+2. Calculate $d = enc_1^{sk}, \quad d \in \mathbb{G}$.
+3. Generate a random value $\mu, \quad \mu \in \mathbb{Z}_q$.
+4. Compute $A_1 = g^{\mu}$, where $g$ is the group generator ($A_1 \in \mathbb{G}$).
+5. Compute $A_2 = (enc_1)^{\mu}, \quad A_2 \in \mathbb{G}$.
+6. Compute $с = H(pk, d, g, enc_1, A_1, A_2)$,
where $pk$ is a corresponding public key of $sk$, $H$ is a hash function.
-6. Compute $z = sk * e + \mu, \quad z \in \mathbb{Z}_q$.
+7. Compute $z = sk * с + \mu, \quad z \in \mathbb{Z}_q$.
-Finally, the proof is $\pi = (A_1, A_2, z)$.
+Finally, the proof is $\pi = (с, z)$.
### Verifier
@@ -639,17 +651,18 @@ TallyCheck(enc, dec, pk, \pi) = true | false
As a result algorithm will return `true` or `false`,
is the verification was succeeded or not respectively.
-Knowing that $\pi$ equals to $(A_1, A_2, z)$,
+Knowing that $\pi$ equals to $(с, z)$,
verifier needs to perform the next steps:
1. Take the first and second elements $enc_1, enc_2$
of the ciphertext $enc = (enc_1, enc_2)$.
-2. Calculate $d = g^{dec} \circ (-enc_2), \quad d \in \mathbb{G}$.
-3. Compute $e = H(pk, d, g, enc_1, A_1, A_2 )$, where $g$ is the group generator.
-4. Verify $g^z == pk^e \circ A_1$.
-5. Verify $enc_1^z == d^e \circ A_2$.
+2. Calculate $d = enc_2 \circ g^{-dec}, \quad d \in \mathbb{G}$.
+3. Calculate $A_1 = g^{z} \circ pk^{-c}, \quad A_1 \in \mathbb{G}$.
+4. Calculate $A_2 = enc_1^{z} \circ d^{-c}, \quad A_2 \in \mathbb{G}$.
+5. Compute $с2 = H(pk, d, g, enc_1, A_1, A_2)$, where $g$ is the group generator.
+6. Verify $с == с2$.
-If step `3` and `4` returns `true` so the final result is `true` otherwise return `false`.
+If step `6` returns `true` so the final result is `true` otherwise return `false`.
## Rationale