BattleZips
  • Awesome Circom
  • 🔬Theory
    • Prerequisite Knowledge
    • Resources
      • White Papers & PDF's
      • Blogs and Writeups
      • Videos
      • Important Entities
      • Communities
    • Proving Schemes
    • Primitives
      • Hash Functions
      • Public Key Cryptosystems
        • Note on L1 key registry → L2 hot key + callback to circuit-optimized hash functions
        • ECDSA & secp256k1
        • EdDSA
      • Merkle Trees
        • What is a Merkle Tree?
        • What is a merkle proof of inclusion?
        • zk-kit
        • Incremental Merkle Trees
        • Sparse Merkle Trees
        • Tree Arity (Binary, Quinary)
      • Semaphore
      • Arithmetic Circuits
  • 🏗️Development
    • Circom Language
      • Installation
      • IDE
      • Signals and Variables
      • Signal Assignment and Constraint Generation
      • Conditional Statements
      • Components and Templates
      • Circuit Compilation
      • Syntax
    • SnarkJS
      • Proving Schemes
      • Powers of Tau
      • ZK Keys
      • Zero Knowledge Proofs
      • On-Chain ZKP
      • Page 2
    • circomlib
      • Basic Math Constraints
      • Multiplexing
      • Hashing
      • EdDSA
      • circomlibjs
    • circom-tester
    • hardhat-circom
    • SHIELD
    • Circomspect
  • 🌆Ecosystem
    • Circom vs Other Solutions
      • Domain-Specific Languages
      • ZK Virtual Machines
      • ZK Ethereum Virtual Machines
    • Communities to Join
    • Recorded Content
    • Projects
  • 🛳️Examples
    • BattleZips V1
      • On the BattleZips Project
      • Docs holder
        • Join Game UML Sequence Diagram
        • Play Game UML Sequence Diagram
        • End Game UML Sequence Diagram
      • ZK Privacy Stack
      • Deploying Artifacts to Prod
      • Browser Client
    • RollupNC
      • Smart Contracts
      • Account/ State Tree
      • Transaction Tree
      • Layer 1 Deposits to Layer 2
      • Layer 2 Transacting
      • Layer 2 Withdrawals to Layer 1
Powered by GitBook
On this page
  • What is a Multiplexer?
  • Why do I Care About Multiplexers?
  • Example
  1. Development
  2. Circom Language

Conditional Statements

The misleading inclusion of the "if" statement in Circom, and the use of multiplexers to actually compute branching logi

PreviousSignal Assignment and Constraint GenerationNextComponents and Templates

Last updated 2 years ago

If you go by the Circom docs, you will be mislead into believing you can quickly create conditional, branching logic using the if operand. This is one of the quickest ways to run into an Error: non-quadratic constrains not allowed! error. In this section, we will explain the use of Multiplexers in Circom to accomplish branched logic.

What is a Multiplexer?

A multiplexer, AKA "MUX", is a way to pass multiple signals through a single interface. In electrical engineering, one use of a a multiplexer is to encode many different TV channels into a single stream of data for transmission where the recipient can multiplex between channels for their desired output signal. A multiplexer in an arithmetic circuit is similar- it allows us to take multiple different signals as input, outputting only one chosen input signal.

Why do I Care About Multiplexers?

Example

Here we provide an example of how one might (incorrectly) attempt to do conditional logic with a Battleship game's hit detection, as well as the correct way to multiplex conditional logic in this case.

See the circomlib > Multiplexing section for more information on the application of multiplexers in the wild.

Incorrect Conditional Logic Computation

DO NOT DO THIS!!!!

template HitShip(n) {

    signal input ship[3]; // x, y, z to hitscan from
    signal input shot[2]; // x, y, to hitscan with
    signal output hit; // 0 if not hit, 1 if hit
    
    var _hit = 0;
    if (ship[2] == 0) {
        for (var i = 0; i < n; i++) {
            var _x = (ship[0] + i == shot[0]);
            var _y = (ship[1] == shot[1]);
            _hit += 1 * (_x == 1 && _y == 1);
        }
    } else {
        for (var i = 0; i < n; i++) {
            var _x = (ship[0] == shot[0]);
            var _y = (ship[1] + i == shot[1]);
            _hit += 1 * (_x == 1 && _y == 1);
        }
    }
    hit <== _hit;
}

Correct Conditional Logic Computation

DO THIS!!!!

template HitShip(n) {

    signal input ship[3]; // x, y, z to hitscan from
    signal input shot[2]; // x, y, to hitscan with
    signal output hit; // 0 if not hit, 1 if hit

    /// COMPUTE HORIZONTAL SHIP ORIENTATION HIT SCAN CASE
    var hHit = 0;
    for (var i = 0; i < n; i++) {
        var _x = (ship[0] + i == shot[0]);
        var _y = (ship[1] == shot[1]);
        hHit += 1 * (_x == 1 && _y == 1);
    }
    /// COMPUTE VERTICAL SHIP ORIENTATION HIT SCAN CASE
    var vHit = 0;
    for (var i = 0; i < n; i++) {
        var _x = (ship[0] == shot[0]);
        var _y = (ship[1] + i == shot[1]);
        vHit += 1 * (_x == 1 && _y == 1);
    }

    /// MUX TO CONDITIONALLY SELECT SHIP ORIENTATION HIT SCAN
    component mux = Mux1();
    mux.c[0] <-- hHit; // assign
    mux.c[1] <-- vHit;
    mux.s <== ship[2];
    hit <== mux.out;
}

Use of if statements will quickly cause circuits that have non-quadratic constraints. This is a consequence of trying to compute one branch of logic without trying to compute the other branch. Essentially, in Circom you must compute all conditional branches of logic and multiplex them to choose the branch you want to proceed with. This is undoubtedly quite expensive, especially as the need for conditional branching switches from binary "if" statements to something closer to a "switch case". Nonetheless, multiplexing between N possibilities is entirely feasible. contains multiple different MUX types showing up to 4 orders- if you really need more than 16 potential branches, you can explore how the underlying template might be resized for your needs. This is likely only in the case of extreme switch cases and would likely be highly inefficient if further conditional / branching logic was applies from this point without R&D.

🏗️
Circomlib
MultiMux
Multiplexing
Time-Division Multiplexer for Analog TV Channels
http://www.gordostuff.com/2011/11/digital-multiplexing-time-division.html