LogoLogo
  • Sign Protocol
    • Introduction
    • FAQ
  • For Hackers
    • Getting Started
  • For Builders
    • Getting Started
      • Fundamentals
      • Tutorials
        • Building a Simple Notary Platform
          • Schema Creation
          • Attestation Creation
          • Querying Attestations
          • Parsing Attestation Data
        • Delegate Attestation Creation
          • Express Backend
          • Solidity
      • Examples
        • Attestation Discord Bot
        • KYC-Gated Smart Contract Access Control
    • Supported Networks
    • Sign Developer Platform
    • Advanced Topics
      • Cross Chain Attestations
      • Hybrid Attestations
      • Schema Hooks
        • Tutorial: Checking Attestation Data
          • Schema Creation
          • Schema Hook
          • Creating an Attestation (Solidity)
      • ZK Attestations
        • Compile a Circuit
        • Create a Schema Hook
    • Querying Data
      • NPM SDK
        • Usage & Examples
      • REST APIs
        • Schemas
        • Attestations
      • GraphQL
        • Schemas
        • Attestations
    • Writing Data
      • NPM SDK
        • Installation
        • Usage
          • Schemas
          • Attestations
        • Examples
        • Changelog
      • Smart Contract
        • EVM
          • Interfaces
            • ISP
            • ISPHook
            • IVersionable
          • Data Models
            • Schema
            • Attestation
            • DataLocation
  • For Thinkers
    • A Future Of Verifiable Trust
    • Effective Attestations
    • Incentive-Aligned Public Good
    • Glossary
      • Attestations
      • Schema
      • Schema Registry
      • Attestation Repository
  • Case Study
    • EthSign
    • KYC-Gated Contract Calls
    • Proof of Audit
    • Developer Onchain Reputation
    • Onboarding Web2 Data
Powered by GitBook
LogoLogo

Copyright Sign 2021-2024

On this page
  • Compile Your Circuit
  • Generate a Witness
  • Generating a Verifier Contract

Was this helpful?

  1. For Builders
  2. Advanced Topics
  3. ZK Attestations

Compile a Circuit

PreviousZK AttestationsNextCreate a Schema Hook

Last updated 6 months ago

Was this helpful?

There are many ZK libraries and languages that can be used with Sign Protocol, each with its pros and cons. We do not aim to cover these similarities and differences and it is up to you to decide which to use. However, we recommend using a library that can generate a Solidity verifier using your compiled circuit. We will use .

First, follow Circom's docs for . If you have never used Circom before, we recommend reading through their . For this tutorial, we will use a non-trivial example circuit, which you can find . The circom file should contain the following:

pragma circom 2.0.0;

include "circomlib/circuits/sha256/sha256.circom";
include "circomlib/circuits/bitify.circom";

/**
 * Wrapper around SHA256 to support bytes as input instead of bits
 * @param  N   The number of input bytes
 * @input  in  The input bytes
 * @output out The SHA256 output of the n input bytes, in bytes
 *
 * SOURCE: https://github.com/celer-network/zk-benchmark/blob/main/circom/circuits/sha256/sha256_bytes.circom
 */
template Sha256Bytes(N) {
  signal input in[N];
  signal output out[32];

  // convert input bytes to bits
  component byte_to_bits[N];
  for (var i = 0; i < N; i++) {
    byte_to_bits[i] = Num2Bits(8);
    byte_to_bits[i].in <== in[i];
  }

  // sha256 over bits
  component sha256 = Sha256(N*8);
  for (var i = 0; i < N; i++) {
    for (var j = 0; j < 8; j++) {
      sha256.in[i*8+j] <== byte_to_bits[i].out[7-j];
    }
  }

  // convert output bytes to bits
  component bits_to_bytes[32];
  for (var i = 0; i < 32; i++) {
    bits_to_bytes[i] = Bits2Num(8);
    for (var j = 0; j < 8; j++) {
      bits_to_bytes[i].in[7-j] <== sha256.out[i*8+j];
    }
    out[i] <== bits_to_bytes[i].out;
  }
}

template Main(N) {
    signal input in[N];
    signal input hash[32];
    signal output out[32];

    component sha256 = Sha256Bytes(N);
    sha256.in <== in;
    out <== sha256.out;

    for (var i = 0; i < 32; i++) {
        out[i] === hash[i];
    }

    log("start ================");
    for (var i = 0; i < 32; i++) {
        log(out[i]);
    }
    log("finish ================");
}

// render this file before compilation
component main = Main(64);

This sha256 circuit will take in two signals as input: the first is an array of size 64 and the second is an array of size 32. The first array will be hashed using the sha256 algorithm, requiring that the output (hash) signal equals the provided hash. Next, we will compile our circuit.

Compile Your Circuit

Your local Circom installation comes with the circom command. To compile your circuit, run:

> circom sha256.circom --r1cs --wasm --sym

Generate a Witness

In your output directory (likely named sha256_js), create a file named input.json. Paste the following in this file:

{
  "in": [
    20, 207, 123, 94, 84, 118, 123, 180, 191, 195, 21, 180, 82, 88, 185, 223,
    207, 101, 103, 247, 201, 113, 113, 87, 111, 84, 191, 243, 87, 47, 134, 143,
    20, 207, 123, 94, 84, 118, 123, 180, 191, 195, 21, 180, 82, 88, 185, 223,
    207, 101, 103, 247, 201, 113, 113, 87, 111, 84, 191, 243, 87, 47, 134, 143
  ],
  "hash": [
    29, 131, 153, 39, 255, 114, 11, 253, 116, 101, 97, 195, 155, 112, 35, 76,
    226, 32, 120, 129, 165, 186, 145, 10, 192, 28, 49, 244, 143, 179, 101, 236
  ]
}

Next, navigate to your build directory and run the following command to generate a witness:

> node generate_witness.js sha256.wasm input.json witness.wtns

Generating a Verifier Contract

> snarkjs powersoftau new bn128 17 pot12_0000.ptau -v
> snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v
> snarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -v
> snarkjs groth16 setup sha256.r1cs pot12_final.ptau sha256_0000.zkey
> snarkjs zkey contribute sha256_0000.zkey sha256_0001.zkey --name="1st Contributor Name" -v
> snarkjs zkey export verificationkey sha256_0001.zkey verification_key.json

Now that you have generated all required files, you can generate a smart contract verifier using the following command:

> snarkjs zkey export solidityverifier sha256_0001.zkey verifier.sol

This will generate a file named verifier.sol in your root project directory. To facilitate a function call for verifyProof(), you can run the following command:

> snarkjs generatecall

When you are ready, proceed to the next page to integrate verifier.sol with a schema hook.

This command will compile your source code into the required files, including the r1cs constraint system file, and wasm files for generating a witness. You can read more about the command flags . From here, you will generate your witness. Note that you do not need a witness to generate a smart contract verifier. Witnesses are used for creating proofs, which will be verified using your schema hook.

This section follows the documentation located . For more information about each step, please refer to Circom's documentation. Run the following commands to complete the Powers of Tau and Phase 2 requirements:

Circom
installation
sample circuit
here
here
here