GithubHelp home page GithubHelp logo

miguelmota / zksnarks-example Goto Github PK

View Code? Open in Web Editor NEW
36.0 3.0 8.0 23 KB

An example of how generate zero-knowledge proofs and verify using an Ethereum smart contract.

Home Page: https://github.com/miguelmota/zksnarks-example

zk zk-snarks zero-knowledge zero-knowledge-proofs ethereum smart-contracts verification proofs blockchain snarkjs

zksnarks-example's Introduction

zkSNARKs Example

An example of how generate zero-knowledge proofs and verify using an Ethereum smart contract.

Tutorial

  • Install circom and snarkjs:

    npm install -g circom
    npm install -g snarkjs

    NOTE: for this demo I used [email protected] and [email protected]

    • Circom is a language for writing arithmetic circuits that can be used in zero-knowledge proofs. Circom stands for circuit compiler.
    • Snarkjs is a JavaScript implementation of zkSNARK schemes which is used to generate proofs given circuits generated with circom.
  • Create a circuit:

    We'll create a circuit that tries to prove we are able to factor a number.

    • The circuit will have 2 private inputs and 1 output.
    • The output signal c must be the value of signal a times signal b.
    • We instantiate the circuit and assign it to the main component. The component main must always exist.

    circuit.circom

    template Multiplier() {
      signal private input a;
      signal private input b;
      signal output c;
      c <== a*b;
    }
    
    component main = Multiplier();

    Ths only thing the circuit enforces is that c equals a times b with the statement c <== a*b which defines the constraint.

  • Compile the circuit with circom:

    circom factor/circuit.circom -o circuit.json

    This will output circuit.json

  • Run setup for the circuit:

    Running the setup method will instantiate key files we'll need:

    snarkjs setup --circuit=circuit.json

    The setup will generate a proving key and a verification key, proving_key.json and verification_key.json respectively.

  • Calculate a witness:

    We'll create a file containing the input parameters.

    • Provide a file with the inputs and it will execute the circuit.
    • Snarkjs will calculate the intermediate signals and the output.
    • The calculated set of signals is the witness.

    For this example, we'll be proving we can factor 56 without revealing the two factor numbers.

    We'll prove that we know that 7 and 8 multiply to 56:

    input.json

    {
      "a": 7,
      "b": 8
    }
    • The zero knowledge proofs prove that we know a set of signals that match the constraints.
    • These signals are the witness.
    • The witness doesn't reveal any of the signals except the public inputs and the outputs.

    We can calculate the witness now:

    snarkjs calculatewitness --circuit=circuit.json --input=input.json

    This generates witness.json with all the signals.

  • Generate proof:

    We'll use the proving key and witness to generate a proof that we the inputs that factor into 56:

    snarkjs proof --witness=witness.json --provingkey=proving_key.json

    This generates proof.json and public.json which is the values of the public inputs and outputs. In this case it's just the output because our inputs were private.

    [
     "56"
    ]
  • Verify proof:

    We can verify a proof using snarkjs:

    $ snarkjs verify --proof=proof.json --verificationkey=verification_key.json --public=public.json
    OK

    This will output OK if correct or INVALID if incorrect.

  • Smart contract to verify proofs:

    snarkjs provides a method to generate a contract to verify proofs onchain:

    snarkjs generateverifier --verificationkey=verification_key.json

    This outputs verifier.sol

    The contract method we'll be using is verifyProof:

    function verifyProof(
            uint[2] a,
            uint[2] a_p,
            uint[2][2] b,
            uint[2] b_p,
            uint[2] c,
            uint[2] c_p,
            uint[2] h,
            uint[2] k,
            uint[1] input
        ) view public returns (bool r) {
        Proof memory proof;
        proof.A = Pairing.G1Point(a[0], a[1]);
        proof.A_p = Pairing.G1Point(a_p[0], a_p[1]);
        proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
        proof.B_p = Pairing.G1Point(b_p[0], b_p[1]);
        proof.C = Pairing.G1Point(c[0], c[1]);
        proof.C_p = Pairing.G1Point(c_p[0], c_p[1]);
        proof.H = Pairing.G1Point(h[0], h[1]);
        proof.K = Pairing.G1Point(k[0], k[1]);
        uint[] memory inputValues = new uint[](input.length);
        for(uint i = 0; i < input.length; i++){
            inputValues[i] = input[i];
        }
        if (verify(inputValues, proof) == 0) {
            return true;
        } else {
            return false;
        }
    }

    As you can see there is a lot going on. Snarkjs conveniently provides a method to generate the transaction input parameters.

    snarkjs generatecall --proof=proof.json --public=public.json

    The output will look similar to this:

    ["0x225074f4c52d6abfbe39070488e9ad4a614c17e954f6dd1f95df298a0eef0a6c", "0x16c7e4b0c01a120fe48c8eb2339a7209e77796328a61e56547b73567016fd75e"],["0x250a2c4eb6c8d434b3fa3c408c1a3ab4a2db6d63c7ba917c9849083c86812832", "0x2f9c617819fec52b3417745eee59319eb56d846b5e428cb81d90a9a1f09beaf4"],[["0x19ab9c29a7e580507cc3054f36f12506d429112faa75e751ddc4c6237344ab1a", "0x099afd70d77234c35b15112b7a9352f6ec2b3030408125b66654631de21c078e"],["0x2d67175e322ab6e6a98921e29c94cdd1ab07db28d62de7e104199361e5092851", "0x0bdc9fd000cdbc79b344fb307c1ea679b2a14f1756a47cbccefe6349265fdd9d"]],["0x2f17a8a96f4f1a37dcf99fceddbb942e94a3a83547b80f4061eaa295d969dccc", "0x086cc7c64c083849eba6161be31f794b359e735e83c25a7ee9475d9943d9b8f5"],["0x26f172ffa1f027799863c43c640ccb632fc664c918138fea026127bdf07c6c0a", "0x0e0dd693317beda6b8bf1ac9024af15a35bee071cc5bdcb2784926df18ba3fb0"],["0x1c23be59028e8095a430b2e5b3768303ec5163a49e2a9b4da7f3a6b30b78a5f1", "0x0318a6a3bd9a7c36e35fc44030fda9dd594965b1cba90c942211028c3f308fb6"],["0x1f84acf96a6d7b112c097feb438dadd8bc56c59f5e466e7d17e33560df87c893", "0x257a236d53fb9a129d5e8239d592bc3173f99ab378df5f5c5a00d4e3fb6983b2"],["0x1c55a602b2237a439ccc899ae6a49e1d08ca66300283500188e5823d246a9321", "0x1c297b898c386684bc32e504317dbfdb09971227d413541f74659fcc2cd8a9a5"],["0x0000000000000000000000000000000000000000000000000000000000000038"]

    The verify function returns true if the public inputs satisfy the proof.

  • Compiling verifier contract:

    Head over to the Ethereum Remix IDE and paste in the smart contract.

    • Compile the smart contract using the correct solidity compiler version.
  • Deploying verifier contract:

    Use the MetaMask extension and connect to a testnet. I chose the Rinkeby testnet for this example.

    • Select Injected Web3 as the environment.
    • Select the Verifier contract and click Deploy.

    Deployment transaction: https://rinkeby.etherscan.io/tx/0x6b7c99bc9b6972e11c3a2918d8fe00b40f0036ebf18d28918a20a80b8d306947

  • Verify proofs using the deployed contract:

    Use the generatecall helper like we did in a previous step and paste it in to the verifyProof input field under Deployed Contracts:

    This is a pure function meaning it doesn't perform any writes. You'll get back a boolean response as you can see in the bottom right below the method input field.

Additional

  • To show general statistics of a circuit, you can run:

    snarkjs info --circuit=circuit.json
  • Print the constraints of the circuit by running:

    snarkjs printconstraints --circuit=circuit.json

Resources

License

MIT

zksnarks-example's People

Contributors

amiller avatar miguelmota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.