Pure Circuits
A circuit is considered pure if it computes its outputs from its inputs without reference to or modification of public state (via the ledger) or private state (via witnesses).
Source: Circuits
Syntax
The pure modifier must follow export (if present):
pure circuit helper(x: Field): Field {
return x * 2;
}
export pure circuit publicHelper(x: Field): Field {
return x * 2;
}
If a pure circuit actually uses ledger operations or witnesses, the compiler rejects it. Marking a circuit pure ensures it appears in the generated PureCircuits type and pureCircuits constant in the TypeScript output.
Source: Circuits, TypeScript target
What Makes a Circuit Impure?
According to the docs, the compiler considers a circuit to be impure if:
- The body contains a ledger operation
- The body calls any impure circuit
- The body calls a witness
Note: Some standard library functions are witnesses and make the caller impure.
What Pure Circuits Can Do
- ✅ Perform calculations
- ✅ Call other pure circuits
- ✅ Call pure standard library functions
- ✅ Use parameters and local variables
- ❌ Read ledger state
- ❌ Modify ledger state
- ❌ Call witnesses
- ❌ Call impure circuits
Use Cases
Mathematical Operations
pure circuit triple(amount: Uint<64>): Uint<64> {
return (amount * 3) as Uint<64>;
}
⚠️ Note: Compact has no division operator —
/is a parse error. Percentage-style math (e.g., a 3% fee) can’t be written asamount * 3 / 100; compute the quotient off-chain, pass it in as a witness, and constrain it in the circuit (see Chapter 7: Witnesses).
Validation Logic
pure circuit isValidAge(age: Uint<8>): Boolean {
return age >= 18 && age <= 120;
}
Type Conversions
pure circuit toBytes(value: Uint<64>): Bytes<32> {
return (value as Field) as Bytes<32>;
}
Using Pure Circuits
Call pure circuits from any circuit:
export ledger counter: Counter;
pure circuit validate(x: Uint<64>): Boolean {
return x > 0 && x < 1000;
}
export circuit process(amount: Uint<64>): [] {
assert(validate(amount), "Invalid amount");
counter.increment(disclose(amount as Uint<16>));
}
TypeScript Integration
The Compact compiler exports pure circuits via pureCircuits in the TypeScript module, allowing them to be used directly without blockchain interaction.
Source: TypeScript target
Benefits of Pure Circuits
- Verification - Compiler enforces purity constraints
- Reusability - Share logic across circuits
- Off-chain use - Available via
pureCircuitsin TypeScript - Clarity - Clear separation of stateful vs stateless logic
Exercises
Complete exercises/03_circuits/04_pure_circuits/.