Skip to main content
Sigvex

Cross-Template Constraint Gap Remediation

How to fix broken constraint chains between template instances by using constrained wiring.

Cross-Template Constraint Gap Remediation

Overview

Related Detector: Cross-Template Constraint Gap

A cross-template constraint gap occurs when signals passed between template instances use unconstrained assignment (<--) instead of constrained wiring (<==). Even if each template is individually sound, the prover can inject arbitrary values at template boundaries, breaking the overall circuit security.

Before (Vulnerable)

template Main() {
    signal input data;
    signal output result;

    component hash = Poseidon(1);
    hash.inputs[0] <== data;

    component verify = Verifier();
    verify.hashValue <-- hash.out;  // BROKEN: unconstrained wiring
    result <== verify.result;
}

After (Fixed – Constrained Wiring)

Replace all <-- wiring between components with <==:

template Main() {
    signal input data;
    signal output result;

    component hash = Poseidon(1);
    hash.inputs[0] <== data;

    component verify = Verifier();
    verify.hashValue <== hash.out;  // CORRECT: constraint chain intact
    result <== verify.result;
}

After (Fixed – Explicit Intermediate with Constraint)

When you need an intermediate signal between components, constrain it on both sides:

template Main() {
    signal input data;
    signal output result;

    component hash = Poseidon(1);
    hash.inputs[0] <== data;

    signal intermediate;
    intermediate <== hash.out;  // Constrained from hash output

    component verify = Verifier();
    verify.hashValue <== intermediate;  // Constrained into verifier
    result <== verify.result;
}

Alternative Mitigations

1. Audit All Component Wiring Systematically

Review every component instantiation and verify that all inputs and outputs use <==. A simple search for <-- adjacent to component signal access (e.g., comp.signal <--) identifies potential gaps.

2. Wrapper Templates for Constraint Enforcement

Create wrapper templates that enforce constrained wiring as part of their interface:

template SafeHash(nInputs) {
    signal input in[nInputs];
    signal output out;

    component h = Poseidon(nInputs);
    for (var i = 0; i < nInputs; i++) {
        h.inputs[i] <== in[i];
    }
    out <== h.out;
}

Common Mistakes

Mixing <-- and <== in multi-component chains: If template A feeds template B feeds template C, a single <-- anywhere in the chain breaks the entire constraint propagation. Every link must use <==.

Assuming component-internal constraints are sufficient: A component’s internal constraints verify relationships between its own signals. They do not constrain the wiring between the component and the parent template. The wiring itself must be constrained.

Using <-- for “performance” reasons: There is no performance benefit to using <-- over <== for component wiring. The <== operator generates both the assignment and the constraint, which is always necessary for inter-template connections.

References