Can you prove that you know the answer to a question, without revealing the answer?

Please do not think that Bitcoin in any way represents a modern distributed ledger. It is basically the Ford T of blockchain, and where…

Photo by Michael Förtsch on Unsplash

Can you prove that you know the answer to a question, without revealing the answer? Here’s zkSnarks, Smart Contracts and Ethereum

Please do not think that Bitcoin in any way represents a modern distributed ledger. It is basically the Ford T of blockchain, and where Ethereum and IOTA can be likened to a Tesla car in comparison.

Overall, Ethereum advanced the Merkle Tree and blockchain chain approach of Bitcoin and added an improved proof of work (with Gas) and smart contracts. With these smart contracts, we could now run trusted code on the blockchain, and where we could pass parameters into and out of functions hosted on the public ledger.

This code, though, can be seen by anyone reviewing the contract, and where they can also see the values used. We thus need methods which can preserve the privacy of the data and code used, and so we turn to 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 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 [View 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

And there, you go. zkSnarks and privacy on Ethereum. If you are interested, here’s the smart contract I created:

https://ropsten.etherscan.io/address/0xa596c5898ef5ce0db5813d0fa3a5102e863560d8

Here is some background material for zkSnarks:

  • Zero-knowledge proof (zkSnark — Blind evaluation problem). ZKP. Outlines zero-knowledge proof.
  • Zero-knowledge proof (zkSnark — Hidden Homomorphic). ZKP. Outlines zero-knowledge proof.
  • zkSNARKs in Go. zkSNARKs. Implementation of zkSNARKs.
  • zkSNARKs in Go (gsnark). zkSNARKs. Implementation of zkSNARKs in Go with gsnark.
  • QAP in zkSNARKs using Go. QAP. Implementation of zkSNARKs QAP.
  • R1CS (Rank 1 Constraint System) in Go. R1CS. Implementation of the method used with zk-SNARKs for zero-knowledge proofs.
  • Zero Knowledge Proof using crypto pairing using MIRACL (zk-SNARK). ZKP. Using crypto pairs for ZKP.

References

[1] Eberhardt, J., & Tai, S. (2018, July). Zokrates-scalable privacy-preserving off-chain computations. In 2018 IEEE International Conference on Internet of Things (iThings) and IEEE Green Computing and Communications (GreenCom) and IEEE Cyber, Physical and Social Computing (CPSCom) and IEEE Smart Data (SmartData) (pp. 1084–1091). IEEE.