QURAS uses zero-knowledge proof called “zk-SNARK”. Using zk-SNARK makes it possible to realize the complete privacy (anonymity) of transactions and smart contracts. zk-SNARK is an abbreviation of “Zero-Knowledge Succinct Non-Interactive Argument of Knowledge”. Succinct means message size is far smaller than the computation amount to be actually executed. Noninteractive means verification can be done without requiring communication between verifiers and approvers in real time. Argument of Knowledge refers to knowledge verification by computation. Even if the zk-SNARK technology is used to hide sender, remittance, and amount information, there are three major algorithms that still can check transactions:
G: Algorithm to generate a key (a proof key (pk) and a verification key (vk) are created from a certain secret value R and a program C, (pk, vk)= G(R,C) )
P: Proof is generated from proof key (pk), information to verify (X) and the input (h) to program C, prf = P(pk, X, h)
V: Verifier verifies the verification from the input (h) to program C, the proof (prf) and verification key (vk), verifies whether or not a verification is correct, “correct or incorrect” is returned. V(vk, h, prf) = True or False. The purpose of this is to perform verification work in a short amount of time with less computation without the approver having to question verifiers.
The execution of zk-SNARK requires the following steps:
Computation Arithmetic Circuit R1CS QAP zk-SNARK
Arithmetic Circuit
To convert transaction-effective functions to a mathematical expression, the logical steps are first broken down to the minimum operations as possible to create an “arithmetic circuit”. When c1, c2, c3 are known for A to be (c1 ˙ c2) ˙ (c1+c3)=7, the values of c1, c2, c3 are not indicated to B, and proving that c1, c2, c3 are known, the first step is to display a mathematical formula as an arithmetic circuit.
Arithmetic circuit is expressed in a gate calculation operator such as a wire that connects a gate, addition, and multiplication. The circuit looks like the mathematical formula below:
R1CS:
Next, the arithmetic circuit will be converted to the rank-1 constraint system (R1CS). R1CS is a sequence of a group of three vectors (a, b, c). The solution of R1CS needs to satisfy vector s, where s needs to satisfy the equation, s . a * s . b - s . c = 0. s. s . a * s . b - s . c = 0. s expresses all input vectors, or in other words, [C1 , C2 , C3 , S1 , S2 , S3]. Since this can express an addition gate in the same way, by adding a virtual variable, ”one”, the s vector will [one , C1 , C2 , C3 , S1 , S2 , S3]. These three gates are as follow:
a=[0,1,0,0,0,0,0]
b=[0,0,1,0,0,0,0]
c=[0,0,0,0,1,0,0]
a=[1,0,0,0,0,0,0]
b=[0,1,0,1,0,0,0]
c=[0,0,0,0,0,1,0]
a=[0,0,0,0,1,0,0]
b=[0,0,0,0,0,1,0]
c=[0,0,0,0,0,0,1]
QAP:
The next step is to convert this R1Cs to the QAP (Quadratic Arithmetic
Programs) format. The above three-vector group can display the array, a(x),
b(x), c(x), which is expressed by x. A polynomial expression exists in which
P(x)=s.a(x) * s.b(x) - s.c(x) , P(x)=T(x)*H(x), meaning if P(x)=T(x)*H(x) is proven,
the above mathematical formula can be verified. By defining s.a(x) as L(x),
s.b(x) as R(x) and s.c(x) asO(x), the mathematical formula that needs to be
proven can be re-written to L(x)*R(x)-O(x)=T(x)*H(x).
1. A select the polynomial expression L, R, O, H according to the above method.
2. B selects a random dot s and calculates E(T(s)).
3. A calculates E(L(s)),E(R(s)),E(O(s)),E(H(s)) based on (E(s) , E(s2),...) which
was
sent from B.
4. B verifies E(L(s)* R(s)-O(s))= E(H(s)* T(s)).
The theory called homomorphic encryption is applied. Homomorphic encryption is defined as a function in which the number x, or E(x) satisfies the following natures:
For almost all x, it is hard to find it once E(x) is found. If an input is different, its output will be different as well. This means that, in the case of x≠y, E(x)≠E(y). If someone knows E(x) and E(y), he or she is able to use E(x) and E(y) E to calculate (x + y). This means that, while x and y are hidden, it can be proven that others may know the result of x + y.
The zk-SNARK technology can be utilized to anonymize transactions on the
QURAS platform. During sending/receiving funds, three types of transactions
can be made possible by the zk- SNARK technology: 1) Private (stealth address
to stealth address), 2) Desheilding (stealth address to public address) and 3)
Shielding (public address to stealth address).
Shielding (from public address to stealth address)
This means encryption of transaction details including sender, recipient,
and transaction amount by using zk-SNARKs. Using it makes it possible to
determine if an encrypted transaction is correct without knowing its user’s
private key in the consensus node.
Transaction’s zk-SNARK
That said, there are two new concepts in using zk-SNARKs – Commitment
and Nullifier. Assuming a remaining balance that is encrypted in the QURAS
blockchain is displayed as Note, from Bitcoin, the concept of Note can be seen
as the similar concept of UTXO. The difference is that Note is encrypted and
does not have transparency like UTXO does. The following will explain how
Verifier verifies Note. Commitment can be considered as Unspent Note while
for Bitcoin, it is the same as Unspent UTXO:
Nullifier is available to prevent duplicate payments, but they are Spent Note.
References that are entered as transactions are published setting their hash
as Nullfiler. Transaction Output is their Hash value and their Commitment will
be published in the blockchain. In the QURAS blockchain, the following keys
are generated first in order to use zk- SNARKs:
- ZK.ProvingKey: This is a key used to generate a verification proof (proof) to be used by a verifier for verification after a creator of an anonymous transaction generates an encrypted transaction.
- ZK.VerifyingKey: This is a key used to verify that a transaction that is encrypted by bonding with an encrypted transaction’s verification proof (proof) is correct.
- ZK.SecretKey: This is a key used to generate zk-SNARKs’ ProvingKey and VerifyingKey.
- ZK.PrimaryInput: This is a value shared and used with a vérifier as an input value for a vérifier to generate ZK.Proof.
- ZK.AuxiliaryInput: This is also a value used to generate ZK.Proof.
- ZK.Proof: This data is for a prover to send to a verifier as proof and does not include prover’s information. ZK.Proof is created by a prover based on ZK.ProvingKey, ZK.PrimaryInput and ZK.AuxiliaryInput. The verifier will proceed with verification using the data and this ZK.Verifying Key.
The following explains what type of items exist in JoinSplit.
- VAmount_Old: This indicates the remaining balance in a transparent account when sending funds from T(transparent account)->A(anonymous account)VAmount_New: This indicates the remaining balance that goes to T for the cases of T->A or A->T.
- MerkleRoot: This is a root hash value of commitment’s Markle Tree before the previous block.
- Nullifier(1, 2): This means a Nullfiler value for 2 Notes that are input.
- Commitment(1, 2): This means a commitment value for a note recorded in output.
- Epk: This is a public key for KA key pairs that are used for encrypting output’s Note. The encryption is done by bonding ESK and a receipient’s PKenc. In other words, the receipient can use his/her own Skenc and EPK to read the encrypted Cenc.
- RandomSeed: This means a byte row for Random used to calculate a proof value for JoinSplit.
- Proof: This indicates zk-SNARKs’ zero-knowledge proof for JoinSplit.
- Cenc: This displays encrypted Note data.
The values of VAmount_Old and VAmount_New cannot be 1 or higher. If these two values are all 1 or higher, the transaction is considered a failure. Also, though a JoinSplit proof and zk-SNARK Verify Key, zk-SNARKs verification is done. If True, the transaction is considered successful. If not True, the transaction is considered a failure.
Encrypted transactions shall include at least one JoinSplit item. When JoinSplit is built, a key pair needs to be generated during the 1st phase for a signature key (JoinSplitSig) to verify JoinSplit. Once JoinSplit generation is complete, JoinSplitPrivKey is used to sign on the body of JoinSplit. After this, JoinSplitSig is input in a transaction to generate a transaction for blockchain broadcasting.
(Assuming that the depth of Note Commitment tree is MerkleDepth.)
In Quras blockchain, it is possible to verify the root value and the correctness
of Markle Tree based on Merkle Tree’s Auth Path theory.
As previously mentioned, there are JoinSplit items in an anonymous transaction. VAmount_old in JoinSplit item means pulling coin(s) out from a transparent balance pool. VAmount_new means an act to put coin(s) into the transparent balance pool. Users can simply check only the remaining balance of the QURAS blockchain’s entire transparent balance pool through JoinSplit’s VAmount_old and VAmount_new. The remaining balance of other applicable accounts cannot be viewed.
There is more than one JoinSplit item, and when a transaction is put into
blockchain, its JoinSplit’s Commitment is added to the blockchain’s Note
Commitment Markle Tree.
Also, JoinSplit’s Nullifier will be registered in the blockchain. When registering
an anonymous transaction, if Tx’s Nullifier is already registered in the
blockchain, the transaction will be recognized as double spend and returned
to the blockchain without being registered twice.
In Nullifer computation, even if a random character string is entered in
the Note, its Nullifier value will be different. This way, Nullifier prevents
double spend.
Smart contract means a voluntary computation can be verified. In addition to using zk- SNARK technology to protect token transaction privacy, it is made possible to perform computations that are verifiable and anonymized.