Syntax

Relevant syntactical rules and conventions

Reserved Keywords

The following strings cannot be used in Circom as identifiers except for their stated purpose

  • signal: Declare a new signal.

  • input: Declare the signal as input.

  • output: Declare the signal as output.

  • public: Declare the signal as public.

  • template: Define a new circuit.

  • component: Instantiate a template.

  • var: Declare a new integer variable.

  • function: Define a new function.

  • return: Return from function.

  • if: Branch based on the result of a conditional expression.

    • NOTE: IF STATEMENTS DO NOT WORK AS NEEDED. SEE Conditional Statements

  • else: Fallback for if control flow construct.

  • for: Loop conditionally based on the result of an expression.

  • while: Loop conditionally based on the result of an expression.

  • do: Loop conditionally based on the result of an expression.

  • log: Print the result of the evaluation.

  • assert: Check the condition at construction time.

    • NOTE: THIS IS NOT A CONSTRAINT. SEE Signal Assignment and Constraint Generation

  • include: Include code of the indicated file.

  • pragma circom: Instruction to check the compiler version.

  • pragma custom_templates: Instruction to indicate the usage of custom templates.

Comments

Comments called be declared as single line comments:

// Example circom comment

as well as multi-line comments:

/*
    Example multi-line comment in circom
*/

Improperly adding your comments may result in compile-time errors that give little to no insight on why the circuit compilation is failing.

Identifiers

Identifiers are declarations of variables, signals, or components that allow their repeated reference. Identifiers inside of must start with "_" or any alphabetical ASCII character, after which all alphabetic and numeric characters alongside "_" and "$"

Functions

As defined by the Circom docs:

In circom, functions define generic abstract pieces of code that can perform some computations to obtain a value or an expression to be returned.

Functions perform a similar role to templates as is the role of variables to signals. Functions allow easy, pre-packaged computation, however they do not work with signals and constrains cannot be enforced within a function.

An example of a function is as follows:

/*
    This function calculates the number of extra bits 
    in the output to do the full sum.
 */

function nbits(a) {
    var n = 1;
    var r = 0;
    while (n-1<a) {
        r++;
        n *= 2;
    }
    return r;
}

Logging

Logging leaves a lot to be desired in the Circom language. Most frustratingly, logging only works with numbers, meaning you cannot log error messages to yourself. While incredibly hacky, we tend to spam unique numbers when we are debugging and need to isolate values:

.
.
.
log(9090909090909090);
log(myComponent.out);
log(1010101010101010);
log(otherComponent.out);
log(8888888888888888);
.
.
.

Last updated