Code Monkey home page Code Monkey logo

circomkit's Introduction

hello, friend.

Twitter Badge Website Dev.to Blog Badge Spotify ENS Domain Badge

notes

Cryptonotes Cryptonotes Cryptonotes

main

TypeScript Rust Circom Redis VSCode Bun Vercel

familiar

Solidity Golang Docker Cuda Python ReactJS SolidJS LaTeX NextJS Huff

see more...

Stats

erhant-stats

Zero-Knowledge

circomkit

halo2vectordb

zkbrainfuck

moonmath

cryptopals

EVM & Solidity

huffd1

blockchatting

simple-blockexplorer

ethernaut-evm-challenges

diamonds

circomkit's People

Contributors

ctrlc03 avatar erhant avatar numtel avatar wp-lai 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  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  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

circomkit's Issues

`fflonk` calldata export bug

The issue is found: for fflonk snarkjs takes the parameters (pubs, proof) instead of (proof, pubs) like it does for the others.

Anyways, Im rewriting that whole part so that we can take Solidity-compatible exports too.

TCKN digit-knowledge circuit

TCKN Wiki

  • Must have 11 digits
  • Sum of first 10 digits mod 10 should give 11th digit
  • Let d[i] denote the i'th digit, 1-indexed. Then,
    • ((d[1] + d[3] + d[5] + d[7] + d[9]) * 7 + (d[2] + d[4] + d[6] + d[8]) * 9) mod 10 should give 10th digit
    • (d[1] + d[3] + d[5] + d[7] + d[9]) * 8 mod 10 should give 11th digit.
  • Also note that 11th digit is an even number

CLI command `circomkit list`

This command will list the built circuits under the configured build folder. It's just a quality-of-life command to see which circuits are built. It could even go beyond and see which inputs are exported, and which protocols are outputted for each.

Old Circomkit for legacy

Just found the first version of Circomkit, written in bash entirely:

#!/bin/bash

cd "${0%/*}"/.. # get to project root
set -e # abort on error

### load CLI environment variables
# proof system to be used, can be: groth16 | plonk | fflonk
CIRCOMKIT_PROOF_SYSTEM="groth16"
# name of the curve to be used: bn128 | bls12381 | goldilocks
CIRCOMKIT_ELLIPTIC_CURVE="bn128" 
# solidity contract export path
CIRCOMKIT_SOLIDITY_PATH="./contracts"
# compiler args, can add --inspect and -c for example
CIRCOMKIT_COMPILER_ARGS="--r1cs --wasm --sym -l ./node_modules -p $CIRCOMKIT_ELLIPTIC_CURVE --inspect"
# circom version
CIRCOMKIT_VERSION="2.1.0"
# colors for swag terminal outputs
CIRCOMKIT_COLOR_TITLE='\033[0;34m' # blue
CIRCOMKIT_COLOR_LOG='\033[2;37m'   # gray
CIRCOMKIT_COLOR_ERR='\033[0;31m'   # red
CIRCOMKIT_COLOR_RESET='\033[0m'    # reset color

### check validness of variables
valid_proof_systems=("groth16" "plonk" "fflonk")
if [[ ! " ${valid_proof_systems[@]} " =~ " ${CIRCOMKIT_PROOF_SYSTEM} " ]]; then
  echo -e "${CIRCOMKIT_COLOR_ERR}Invalid proof system: $CIRCOMKIT_PROOF_SYSTEM${CIRCOMKIT_COLOR_RESET}"
  exit 1
fi
valid_elliptic_curves=("bn128" "bls12381" "goldilocks")
if [[ ! " ${valid_elliptic_curves[@]} " =~ " ${CIRCOMKIT_ELLIPTIC_CURVE} " ]]; then
  echo -e "${CIRCOMKIT_COLOR_ERR}Invalid elliptic curve: $CIRCOMKIT_ELLIPTIC_CURVE${CIRCOMKIT_COLOR_RESET}"
  exit 1
fi 

## Function definitions
# Generate types from a circuit template (incomplete)
type() {
  set -e

  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating types ===${CIRCOMKIT_COLOR_RESET}" 
  local CIRCUIT=$1
  local SYM=./build/$CIRCUIT/$CIRCUIT.sym

  # choose lines with 1 dot only (these are the signals of the main component), extract their names
  local MAIN_SIGNALS=$(cat $SYM | awk -F '.' 'NF==2 {print $2}')

  # get the unique signal names
  local MAIN_SIGNAL_NAMES=$(echo "$MAIN_SIGNALS" | awk -F '[' '{print $1}' | uniq)

  # get the last signal for each signal name
  local SIGNALS=""
  for SIGNAL in $MAIN_SIGNAL_NAMES; do
    SIGNALS+="$(echo "$MAIN_SIGNALS" | grep $SIGNAL | tail -n 1) "
  done
  echo "$SIGNALS"

  echo -e "\n${CIRCOMKIT_COLOR_LOG}Types generated!${CIRCOMKIT_COLOR_RESET}" 
}


# Commence a circuit-specific setup
setup() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Circuit Setup ($CIRCOMKIT_PROOF_SYSTEM) ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1                                    # circuit name
  local P1_PTAU=$2                                    # path to phase-1 ptau
  local NUM_CONTRIBS=$3                               # number of contributions (for groth16)
  local CIRCUIT_DIR=./build/$CIRCUIT                  # circuit directory
  local PROVER_KEY=$CIRCUIT_DIR/prover_key.zkey
  local VERIFICATION_KEY=$CIRCUIT_DIR/verifier_key.json

  # check if P1_PTAU exists
  if [ ! -f "$P1_PTAU" ]; then
    echo -e "PTAU file ${CIRCOMKIT_COLOR_ERR}${P1_PTAU} does not exist.${CIRCOMKIT_COLOR_RESET}"
    exit 1
  fi

  if [[ "$CIRCOMKIT_PROOF_SYSTEM" == "groth16" ]]; then
    local P2_PTAU=$CIRCUIT_DIR/phase2_final.ptau         # phase-2 ptau
    local CUR=000                                       # zkey id, initially 0

    # if Groth16, circuit specific ceremony is needed
    # start phase-2 ceremony (circuit specific)
    echo -e "${CIRCOMKIT_COLOR_LOG}this may take a while...${CIRCOMKIT_COLOR_RESET}"
    snarkjs powersoftau prepare phase2 $P1_PTAU $P2_PTAU -v

    # generate a zkey that contains proving and verification keys, along with phase-2 contributions
    snarkjs groth16 setup \
      $CIRCUIT_DIR/$CIRCUIT.r1cs \
      $P2_PTAU \
      $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey
    
    # get rid of phase-2 ptau
    rm $P2_PTAU

    # make contributions (001, 002, ...)
    for NEXT in $(seq -f "%03g" 1 ${NUM_CONTRIBS})
    do
      echo "Making Phase-2 Contribution: ${NEXT}"
      snarkjs zkey contribute \
        $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey \
        $CIRCUIT_DIR/${CIRCUIT}_${NEXT}.zkey -v

      rm $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey

      CUR=$NEXT
    done
    echo "Phase 2 Complete."

    # rename key to the prover key
    mv $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey $PROVER_KEY
  else
    # otherwise, we can use that phase-1 ptau alone
    snarkjs $CIRCOMKIT_PROOF_SYSTEM setup $CIRCUIT_DIR/$CIRCUIT.r1cs \
      $P1_PTAU \
      $PROVER_KEY
  fi

  # export
  snarkjs zkey export verificationkey $PROVER_KEY $VERIFICATION_KEY

  echo -e "${CIRCOMKIT_COLOR_LOG}Generated keys\n\tProver key: $PROVER_KEY\n\tVerification key: $VERIFICATION_KEY${CIRCOMKIT_COLOR_RESET}"
}

# Compile the circuit, outputting R1CS and JS files
compile() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Compiling the circuit ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1
  local CIRCOM_IN=./circuits/main/$CIRCUIT.circom
  local CIRCOM_OUT=./build/$CIRCUIT
  
  # create build dir if not exists already
  mkdir -p $CIRCOM_OUT

  # compile with circom
  echo "circom $CIRCOM_IN -o $CIRCOM_OUT $CIRCOMKIT_COMPILER_ARGS"
  circom $CIRCOM_IN -o $CIRCOM_OUT $CIRCOMKIT_COMPILER_ARGS

  echo -e "${CIRCOMKIT_COLOR_LOG}Built artifacts under $CIRCOM_OUT${CIRCOMKIT_COLOR_RESET}"
}


# Clean build files
clean() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Cleaning artifacts ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1
  local CIRCUIT_DIR=./build/$CIRCUIT
  local TARGET=./circuits/main/$CIRCUIT.circom

  rm -rf $CIRCUIT_DIR
  rm -f $TARGET

  echo -e "${CIRCOMKIT_COLOR_LOG}Deleted $CIRCUIT_DIR and $TARGET${CIRCOMKIT_COLOR_RESET}"
}

# Exports a solidity contract for the verifier
contract() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating Solidity verifier ===${CIRCOMKIT_COLOR_RESET}" 
  local CIRCUIT=$1
  local CIRCUIT_DIR=./build/$CIRCUIT

  snarkjs zkey export solidityverifier \
    $CIRCUIT_DIR/prover_key.zkey \
    $CIRCUIT_DIR/verifier.sol

  echo -e "${CIRCOMKIT_COLOR_LOG}Contract created at $CIRCUIT_DIR/verifier.sol!${CIRCOMKIT_COLOR_RESET}"
}


# Exports a solidity contract for the verifier
calldata() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Exporting calldata ===${CIRCOMKIT_COLOR_RESET}" 
  local CIRCUIT=$1
  local INPUT=$2 
  local CIRCUIT_DIR=./build/$CIRCUIT

  snarkjs zkey export soliditycalldata  \
    $CIRCUIT_DIR/$INPUT/public.json \
    $CIRCUIT_DIR/$INPUT/proof.json

  echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}"
}

# Debug a witness
debug() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Debugging witness ===${CIRCOMKIT_COLOR_RESET}" 
  local CIRCUIT=$1
  local INPUT=$2 
  local CIRCUIT_DIR=./build/$CIRCUIT
  local OUTPUT_DIR=./build/$CIRCUIT/$INPUT      # directory for proof & public signals
  local INPUT_DIR=./inputs/$CIRCUIT             # directory for inputs

  snarkjs wtns debug \
    $CIRCUIT_DIR/${CIRCUIT}_js/$CIRCUIT.wasm \
    $INPUT_DIR/$INPUT.json \
    $OUTPUT_DIR/witness.wtns \
    $CIRCUIT_DIR/$CIRCUIT.sym

  echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}"
}

# Instantiate the main component
instantiate() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Creating main component ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1

  # parse json for the circuit, trim first and last lines, and then remove all whitespace
  local MATCH=$(sed -n "/ *\"${CIRCUIT}\": *{/, /^  *}[, ]$/p" ./circuits.json | sed '1d;$d' | tr -d "[:space:]")
  if [ -z "$MATCH" ] 
  then
    echo -e "${CIRCOMKIT_COLOR_ERR}No such circuit found!${CIRCOMKIT_COLOR_RESET}" 
    exit
  fi

  # create JSON object
  local JSON_IN="{\"version\":\"${CIRCOMKIT_VERSION}\",$MATCH}"

  # generate the circuit main component
  local OUTDIR="./circuits/main/$CIRCUIT.circom"
  npx ejs ./ejs/template.circom -i $JSON_IN -o $OUTDIR

  echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}"
}

# Generate a proof
prove() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating proof ===${CIRCOMKIT_COLOR_RESET}" 
  local CIRCUIT=$1
  local INPUT=$2 
  local CIRCUIT_DIR=./build/$CIRCUIT
  local OUTPUT_DIR=$CIRCUIT_DIR/$INPUT

  snarkjs $CIRCOMKIT_PROOF_SYSTEM prove \
    $CIRCUIT_DIR/prover_key.zkey \
    $OUTPUT_DIR/witness.wtns \
    $OUTPUT_DIR/proof.json \
    $OUTPUT_DIR/public.json

  echo -e "${CIRCOMKIT_COLOR_LOG}Generated under $OUTPUT_DIR${CIRCOMKIT_COLOR_RESET}"
}

# Verify a witness & proof
verify() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Verifying proof ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1
  local INPUT=$2
  local CIRCUIT_DIR=./build/$CIRCUIT

  snarkjs $CIRCOMKIT_PROOF_SYSTEM verify \
    $CIRCUIT_DIR/verifier_key.json \
    $CIRCUIT_DIR/$INPUT/public.json \
    $CIRCUIT_DIR/$INPUT/proof.json

  echo -e "${CIRCOMKIT_COLOR_LOG}Verification complete.${CIRCOMKIT_COLOR_RESET}"
}

# Calculates the witness for the given circuit and input
witness() {
  echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Computing witness ===${CIRCOMKIT_COLOR_RESET}"
  local CIRCUIT=$1
  local INPUT=$2
  local JS_DIR=./build/$CIRCUIT/${CIRCUIT}_js   # JS files for the circuit
  local OUTPUT_DIR=./build/$CIRCUIT/$INPUT      # directory for proof & public signals
  local INPUT_DIR=./inputs/$CIRCUIT             # directory for inputs
  local WITNESS=$OUTPUT_DIR/witness.wtns        # witness output

  mkdir -p $OUTPUT_DIR
 
  node $JS_DIR/generate_witness.js \
    $JS_DIR/$CIRCUIT.wasm \
    $INPUT_DIR/$INPUT.json \
    $WITNESS

  echo -e "${CIRCOMKIT_COLOR_LOG}Generated\n\tWitness: $WITNESS${CIRCOMKIT_COLOR_RESET}"
}

## CLI
# default values
NUM_CONTRIBS=1
INPUT="default"
P1_PTAU="./ptau/powersOfTau28_hez_final_12.ptau"

# get arguments
while getopts "f:c:n:i:p:d:" opt; do
  case $opt in
    # function to call
    f) 
      FUNC="$OPTARG"
      ;;
    # circuit name
    c) 
      CIRCUIT="$OPTARG"
      ;;
    # number of contributions
    n) 
      NUM_CONTRIBS="$OPTARG"
      ;;
    # input name
    i) 
      INPUT="$OPTARG"
      ;;
    # phase-1 ptau path
    p) 
      P1_PTAU="$OPTARG"
      ;;
    # invalid option
    \?) 
      echo "Invalid option -$OPTARG" >&2
      exit 1
      ;; 
  esac
      
  case $OPTARG in
    -*) echo "Option $opt needs a valid argument"
    exit 1
    ;;
  esac
done

# parse circuit & input paths via basename
# TODO, maybe not needed
CIRCUIT=$(basename $CIRCUIT .circom)
INPUT=$(basename $INPUT .json)

case $FUNC in
  clean)
    clean $CIRCUIT
    ;;
  contract) 
    contract $CIRCUIT
    ;;
  calldata) 
    calldata $CIRCUIT $INPUT
    ;;
  compile) 
    instantiate $CIRCUIT && compile $CIRCUIT
    ;;
  debug) 
    debug $CIRCUIT $INPUT
    ;;
  instantiate) 
    instantiate $CIRCUIT
    ;;
  type) 
    type $CIRCUIT
    ;;
  setup) 
    setup $CIRCUIT $P1_PTAU $NUM_CONTRIBS
    ;;
  keygen) 
    compile $CIRCUIT && setup $CIRCUIT $P1_PTAU $NUM_CONTRIBS
    ;;
  prove) 
    witness $CIRCUIT $INPUT && prove $CIRCUIT $INPUT
    ;;
  witness) 
    witness $CIRCUIT $INPUT
    ;;
  verify) 
    verify $CIRCUIT $INPUT
    ;;
  *) 
    echo "Usage:"
    echo "  -f <function>"
    echo "    clean        Cleans the build artifacts"
    echo "    contract     Export Solidity verifier"
    echo "    calldata     Export Solidity calldata for verification"
    echo "    compile      Compile the circuit"
    echo "    instantiate  Instantiate the main component"
    echo "    type         Generate types for TypeScript"
    echo "    setup        Phase-2 setup for the circuit"
    echo "    witness      Generate witness from an input"
    echo "    prove        Prove an input"
    echo "    verify       Verify a proof & public signals"
    echo "    keygen       Shorthand for compile & setup"
    echo "  -c <circuit-name>"
    echo "  -n <num-contributions> (default: $NUM_CONTRIBS)"
    echo "  -i <input-name>"
    echo "  -p <phase1-ptau-path>"
    ;;
esac

Tests to-do

Need unit-tests for Circomkit functions.

Also check: how to install Circom in a Github workflow?

Use Parcel

Multiple target is buggy with generating types, but can be done within a script with using Parcel API

feat: Allow to generate the C witness calculator on compilation

Currently, when compiling a circuit, it is not possible to generate the C witness calculator files. By adding a optional config entry, we can decide whether to generate those files or not.

Would you be happy to have this feature in?

ps. great work with circomkit, we are just now integrating it in maci, and having this option would make it much easier for us to integrate it in our workflows.

circomkit:setup

I was wondering if it's completely necessary to perform this step? https://github.com/erhant/circomkit/blob/main/src/circomkit.ts#L417

The ptau(s) that circomkit downloads are from the Hermez phase1 ceremony, which are ready to be used in a phase2 ceremony.

ps. the base url of the ptau files should be updated just to be safe - seems like they have moved to google storage

EDIT: issue breakdown

  • Remove these lines and use existing PTAU instead of thats being created ptau2init there
  • Update base URL for Perpetual Powers of Tau urls
  • Add an extract function that looks for the zKey (w.r.t circuit name and configured protocol) and generates the vKey
  • Add CLI wrapper that calls extract
  • No need to check if PTAUs for larger constrain counts exist as you mentioned above, but maybe we can add a comment TODO: check for performance gains when larger PTAUs are found instead of the target PTAU; I want to check that out sometime :)

`proof.json` and `public.json` should be protocol-specific

For example, groth16_proof.json & groth16_public.json and such. The reason is, when you change protocols the previous results will be overwritten due to them using the same path.

Warning

This would be a breaking change due to pathing.

Parallel testing

Consider the following test (of a logical OR gate):

await circuit.expectPass({ in: [0, 0] }, { out: 0 });
await circuit.expectPass({ in: [0, 1] }, { out: 0 });
await circuit.expectPass({ in: [1, 0] }, { out: 0 });
await circuit.expectPass({ in: [1, 1] }, { out: 1 });

If we were to use Promise.all for these, we get errors. Need to dive deeper into why that happens.

Add a symbol viewer function

For example, it should output a list of pairs which the CLI prints out as something like:

Symbol Value
main.in 1
main.comp.in1 2
main.comp.in1 3
main.out 4

and such.

Specifying a custom dir with "dirCircuits"

If I specify a custom directory for my circuit templates (e.g. src) and run circomkit compile it still creates a circuits/main/circuit.circom folder for its component. It fails because the relative path generated within that circuit is wrong. "../circuit.circom" doesn't exist in that folder.

I think the right folder for components should be src/main/circuit.circom.

The following line could be the problem.

const targetDir = `./circuits/${directory}`;

Does it make sense? Or am I missing something?

Allow circuit-specific Circomkit config overrides

For example, we may set plonk as the Circomkit protocol in circomkit.json, but we would also like something such as:

{
  "multiplier_3": {
    "file": "multiplier",
    "template": "Multiplier",
    "params": [3],
    "overrides:" {
        // circomkit overrides here!
        "version": "2.1.6",
        "protocol": "groth16"
    }
  },
}

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.