snarkvm_circuit_environment/helpers/
constraint.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Copyright 2024 Aleo Network Foundation
// This file is part of the snarkVM library.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{prelude::*, *};
use snarkvm_fields::PrimeField;

#[derive(Clone, Debug)]
pub struct Constraint<F: PrimeField>(
    pub(crate) Scope,
    pub(crate) LinearCombination<F>,
    pub(crate) LinearCombination<F>,
    pub(crate) LinearCombination<F>,
);

impl<F: PrimeField> Constraint<F> {
    /// Returns the number of non-zero terms required by this constraint.
    pub(crate) fn num_nonzeros(&self) -> (u64, u64, u64) {
        let (a, b, c) = (&self.1, &self.2, &self.3);
        (a.num_nonzeros(), b.num_nonzeros(), c.num_nonzeros())
    }

    /// Returns `true` if the constraint is satisfied.
    pub(crate) fn is_satisfied(&self) -> bool {
        let (scope, a, b, c) = (&self.0, &self.1, &self.2, &self.3);
        let a = a.value();
        let b = b.value();
        let c = c.value();

        match a * b == c {
            true => true,
            false => {
                eprintln!("Failed constraint at {scope}:\n\t({a} * {b}) != {c}");
                false
            }
        }
    }

    /// Returns a reference to the terms `(a, b, c)`.
    pub fn to_terms(&self) -> (&LinearCombination<F>, &LinearCombination<F>, &LinearCombination<F>) {
        (&self.1, &self.2, &self.3)
    }
}

impl<F: PrimeField> Display for Constraint<F> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (scope, a, b, c) = (&self.0, &self.1, &self.2, &self.3);
        let a = a.value();
        let b = b.value();
        let c = c.value();

        match (a * b) == c {
            true => write!(f, "Constraint {scope}:\n\t{a} * {b} == {c}\n"),
            false => write!(f, "Constraint {scope}:\n\t{a} * {b} != {c} (Unsatisfied)\n"),
        }
    }
}