Making Commitments
Zero Knowledge Proofs involve making a commitment to data and not revealing it. Overall, there are three main methods we can use to create this commitment: Hash-based, Pedersen and polynomial.
Hash-based commitments
With hash-based, we basically create a hash of the data and then can reveal later that we can match the data to the hash.
Pedersen commitments
With a Pedersen commitment, Bob has a secret, and then creates a random number (r), and then generates a commitment (c) from the secret and the random value). At some time in the future, Bob can reveal to Alice that he has the secret value:
To register the secret initially, we take two large prime numbers (p and q) and we create a generator value (g) which is of the order of q and a subgroup of Z∗p. Then s becomes a secret from 0 to Zq, and we calculate:
The sender now creates a commitment for a message (m) and with a random number (r):
The sender can then send c to the receiver. Next, the sender will then reveal m and r for the commitment, and the receiver verifies with:
If the values match, the receiver has proven the commitment. The coding of this is here:
Polynomial commitments
With polynomial commitments, Bob can commit to a polynomial, which can be evaluated to specific points. For this we can implement with zkSnarks. These allow us to prove things, without actually revealing the values we have used. For example, a student (Peggy) may be posed with:
y=3x²+2x+5
and be asked to show they have a valid answer for x and y, and where they do not reveal these values. In this case, a value of x=1 will give a y value of 10. In zkSnarks, the Teacher (Victor) then just receives a zkSnarks result for the proof, and they can check it is valid.
Integrating zkSnarks into smart contracts
With a zkSnark — a non-interactive adaptive argument of knowledge — we provide a short proof from a Prover to one or more verifiers that we have specific knowledge of some private data and of a function (f). The proof is fast to prove. And so, zkSnarks can then be integrated into Ethereum and where we can prove things (such as the ownership of a private key) without actually revealing the data. One of the best integrations is ZoKrates [here], and which is a tool kit to build smart contracts which hide private data [1]:
So let’s take a simple example of using the ZoKrates toolkit, and where Peggy must prove that she knows the solution to:
y=3x²+x+4
for x=1. The answer is y=8, so Peggy will produce a zero-knowledge proof that proves she knows this answer. But we want to keep the values private from others observing the smart contract, so in ZoKrates we create a script with:
// y=ax^2 + bx + c
// Pass: a, b, c. And y solution for x
def main(field a, field b, field c, private field x,private field y) -> bool:
field y1=a*x**2 + b*x+ c
bool rtn = if y==y1 then true else false fi
return rtn
In this case, a, b, c and x will be kept private to the smart contract, and we will return a true if the y value passed is correct, otherwise a false. Initially, we enable the ZoKrates plug-in with Remix and add the code:
Next, we can compute a result to check that it works. For example, if we have x=0, then the y value will be 4:
Next we produce a verification key and a proving key:
These keys will be used in the smart contract to support the privacy of the values. In this case, we get:
{"alpha": ["0x089ed4888f41931fac110f003ff613b4750449e2f990663c643bae12c672bc58","0x2f8f54e74cf24541bccba8d1f16c90fc6d8c01090fae06c1f16ee085fb85dec8"],"beta": [["0x1cdc8f275521ebb2faf09ae30a5eac74e8e2b5152a2d978e9d7a5bb696c12f32","0x09aa8a8fa86e8f4d7b457eb4793410556bb0979b01ecb55ded4d494a37aec21b"],["0x1cf6a01fc82803cbfe45c42bd7bd1db9748a8f67b0bbc9aaf54808b9c453b42e","0x26b05a277c1d98c21976df85845a1d204a94a79a5d747264b3a5794fad0cf5ae"]],"gamma": [["0x01321a99414f9db2867bc1cfe8a19b70c051f32c96666053f772905fa9ab8576","0x17e4abd457ea655511e3229c62c45691f62caa0aae7ec75697629db570a5dc21"],["0x0114072fc2710a59abe31ddaf8b53225205815ee2987163722b11852ed65cc40","0x11b513466f621a18e1c209391812814bf03032f99ea1bb8c01b2fb9f0177e50a"]],"delta": [["0x2b00997c7fc044befd5a310c8b6a26399d52ddb7f47d2938abbe29244c2ad744","0x1a8088d98d49fcbceb95fdd351780bee1a066d58324e7e675582e72b2eaca65a"],["0x0f022357f4e65fe556e5c78723684acb9ae3be1fed101fc38edc8aca077438e7","0x0e64491b0174e664a3d0a1898241b2dba808eb1beaf8b26c7ec4ac71ee9ac52f"]],"gamma_abc": [["0x147bce99c514c468014675b34d9959fc5de824a6a45d0968fd0c218a76f7ea6d","0x042d985cdc9e13519a2d7c1bccbc3e4750ba128432b329597e686a31cd363d86"],["0x21e9747031ddc9e43ca4396cfc429357a20f6cc2af0a46cbe30cd64b4d8eb55c","0x03b1d04e0c381414e51c692b46cef7f8d62a908b658e9c9b1e3998f695a886cf"],["0x0bbcedb7a4b5fc0b3299918427082ccf021180c0cd190762adcc19b4605b08a5","0x126148d21860b5f3083ad256a1a13028492128b9975b1ef7c84221fd3dcdc7d0"],["0x01aa789a674a6729ce8549bb2a6d6c7fb8887b34aa7f76c216e673210cb6fef2","0x15e5af7472d5735b278e12fc4dec1ae75433bb6045f9d1420890b71ca554b490"],["0x1821546afc045ec3f216c53d042488309917f07f38d2c6be4cee266de58881fa","0x0e55cc31831a16f7c92f701a729fac14bbf5d0417955934516c858435be0ecd2"]]}
Next, we can generate the zkSnarks proof:
This defines the proof value and the inputs:
{"proof": {"a": ["0x005d91a2588796cc9bea596d8c01430a3ee898a7e989badf9d4cb92fe9baee68","0x2a9479f0cb4b401aa3a232c2dca12135ad983ddd5a19e7996d7725d0342f95b4"],"b": [["0x07030f16f087d6dcde6cdcba39663514bfae47f228ccffe2392ca9c425369395","0x1591320f39698a30a524b722c6799bbf05ee07ca24345192979b698316cc1d96"],["0x11fdcf9c76c6b9f61a5595fd787f33024bd5c47b141a3ae4b50e707552896f38","0x28d4238b0d8fe81bd2bc5d99ce6b274dcb84737796e6ec05abcf9a04d0da37de"]],"c": ["0x1cf289fe4d8dba90bdde741beec6e7e40c21f6442fca1b4a37814e2b396eabb7","0x2abd2302a1622d742d6c6c7ad7e8c630399614be9e4dd3fe0205db6f0ce292b6"]},"inputs": ["0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000004","0x0000000000000000000000000000000000000000000000000000000000000001"]}
The parameters will pass into the smart contract can then be:
[[“0x005d91a2588796cc9bea596d8c01430a3ee898a7e989badf9d4cb92fe9baee68”,”0x2a9479f0cb4b401aa3a232c2dca12135ad983ddd5a19e7996d7725d0342f95b4"],[[“0x07030f16f087d6dcde6cdcba39663514bfae47f228ccffe2392ca9c425369395”,”0x1591320f39698a30a524b722c6799bbf05ee07ca24345192979b698316cc1d96"],[“0x11fdcf9c76c6b9f61a5595fd787f33024bd5c47b141a3ae4b50e707552896f38”,”0x28d4238b0d8fe81bd2bc5d99ce6b274dcb84737796e6ec05abcf9a04d0da37de”]],[“0x1cf289fe4d8dba90bdde741beec6e7e40c21f6442fca1b4a37814e2b396eabb7”,”0x2abd2302a1622d742d6c6c7ad7e8c630399614be9e4dd3fe0205db6f0ce292b6"]]
for (a=3, b=1, c=4 and x=1):
[“0x0000000000000000000000000000000000000000000000000000000000000003”,”0x0000000000000000000000000000000000000000000000000000000000000001",”0x0000000000000000000000000000000000000000000000000000000000000004",”0x0000000000000000000000000000000000000000000000000000000000000001"]
Now we can create the Solidity code for the smart contract:
Within this, there is a verifyTx() function and which will expose the smart contract for external access:
function verifyTx(Proof memory proof, uint[4] memory input) public view returns (bool r) {uint[] memory inputValues = new uint[](4);for(uint i = 0; i < input.length; i++){inputValues[i] = input[i];}if (verify(inputValues, proof) == 0) {return true;} else {return false;}}
We can now compile this using the Solidity compiler:
Next, we can upload the smart contract code to a test network. For this we link Remix to our wallet on the Ropsten test network:
It then takes up to 30 seconds for the smart contract to be mined and deployed:
Once it is deployed, we will get a transaction validation which defines that it has been created at a given address
Then we have the contact here:
We can now verify and publish the contract. This requires us to provide the conde that was used to create the contract:
After this, we define the licence and compiler version:
and the code:
Again, we wait up to 30 seconds, after which the contract is published:
The details of the code are then defined with the contract:
Next, we can click on the Contract tab to test it and see can pass values into verifyTx:
Next, we will create a zero knowledge proof for x=1, a=3, b=1, and c=4, with a y value of 8:
This gives the right proof, but when we try the wrong values, the verification is false:
Conclusions
Go zero … other methods are here: