snarkvm_circuit_environment/helpers/
constraint.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::{prelude::*, *};
17use snarkvm_fields::PrimeField;
18
19#[derive(Clone, Debug, Hash)]
20pub struct Constraint<F: PrimeField>(
21    pub(crate) Scope,
22    pub(crate) LinearCombination<F>,
23    pub(crate) LinearCombination<F>,
24    pub(crate) LinearCombination<F>,
25);
26
27impl<F: PrimeField> Constraint<F> {
28    /// Returns the number of non-zero terms required by this constraint.
29    pub(crate) fn num_nonzeros(&self) -> (u64, u64, u64) {
30        let (a, b, c) = (&self.1, &self.2, &self.3);
31        (a.num_nonzeros(), b.num_nonzeros(), c.num_nonzeros())
32    }
33
34    /// Returns `true` if the constraint is satisfied.
35    pub(crate) fn is_satisfied(&self) -> bool {
36        let (scope, a, b, c) = (&self.0, &self.1, &self.2, &self.3);
37        let a = a.value();
38        let b = b.value();
39        let c = c.value();
40
41        match a * b == c {
42            true => true,
43            false => {
44                eprintln!("Failed constraint at {scope}:\n\t({a} * {b}) != {c}");
45                false
46            }
47        }
48    }
49
50    /// Returns a reference to the terms `(a, b, c)`.
51    pub fn to_terms(&self) -> (&LinearCombination<F>, &LinearCombination<F>, &LinearCombination<F>) {
52        (&self.1, &self.2, &self.3)
53    }
54}
55
56impl<F: PrimeField> Display for Constraint<F> {
57    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58        let (scope, a, b, c) = (&self.0, &self.1, &self.2, &self.3);
59        let a = a.value();
60        let b = b.value();
61        let c = c.value();
62
63        match (a * b) == c {
64            true => write!(f, "Constraint {scope}:\n\t{a} * {b} == {c}\n"),
65            false => write!(f, "Constraint {scope}:\n\t{a} * {b} != {c} (Unsatisfied)\n"),
66        }
67    }
68}