Signals and Variables
Data vessels in Circom
What is a Signal?
From the official Circom documentation:
The arithmetic circuits built using circom operate on signals, which contain field elements in Z/pZ. Signals can be named with an identifier or can be stored in arrays and declared using the keyword signal. Signals can be defined as input or output, and are considered intermediate signals otherwise.
Let's break down this description.
What is a Variable?
Signals are immutable, meaning that they can only be assigned once. This is a feature, not a bug! Before understanding variables, let's quickly go over the concept of unknowns. From the Circom docs:
At compilation time, the content of a signal is always considered unknown (see Unknowns), even if a constant is already assigned to them. The reason for that is to provide a precise decidable definition of which constructions are allowed and which are not, without depending on the power of the compiler to detect whether a signal has always a constant value or not.
pragma circom 2.0.0; template A(n1, n2){ // known signal input in1; // unknown signal input in2; // unknown var x = 0; // known var y = n1; // known var z = in1; // unknown } component main = A(1, 2);
Here we get the first introduction to variables. Variables assist in the computation of information that does not need immediate constraint. For instance, BattleZips constructs the two possible board states (horizontal and vertical, see conditional statements for elaboration) as variables before assigning the value held in the variable to the multiplexer input signals.
Signal Tagging
In Circom 2.1, the concept of signal tagging was introduced. From the official Circom docs:
"Signal Tags circom 2.1.0 introduces a new feature called signal tags. Tags can be defined during the declaration of any signal in a template. The tag list is indicated between brackets right before the signal name"
signal (input/output) {tag_1,...,tag_n} signalname;
The example can initially be a bit confusing, perhaps leading one to believe that there is a predefined list of tags:
template IsZero() { signal input in; signal output {binary} out; signal inv; inv <-- in!=0 ? 1/in : 0; out <== -in*inv +1; in*out === 0; }
In practice, however, this is an example of a properly built component that will facilitate tagging. The binary
tag is arbitrary, however the constraints applied within the component mean that, when extending IsZero
in your codebase, input signals will be forced to use the binary
tag, and signals tagged with binary
that are not actually binary will fail the constraint.
This feature is not required for a functioning code base, but is recommended for a polished, secure circuit.
Last updated