snarkvm_r1cs/
namespace.rs

1// Copyright (C) 2019-2023 Aleo Systems 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// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{errors::SynthesisError, ConstraintSystem, LinearCombination, Variable};
16use snarkvm_fields::Field;
17
18use std::marker::PhantomData;
19
20/// This is a "namespaced" constraint system which borrows a constraint system
21/// (pushing a namespace context) and, when dropped, pops out of the namespace context.
22pub struct Namespace<'a, F: Field, CS: ConstraintSystem<F>>(pub(super) &'a mut CS, pub(super) PhantomData<F>);
23
24impl<F: Field, CS: ConstraintSystem<F>> ConstraintSystem<F> for Namespace<'_, F, CS> {
25    type Root = CS::Root;
26
27    #[inline]
28    fn one() -> Variable {
29        CS::one()
30    }
31
32    #[inline]
33    fn alloc<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
34    where
35        FN: FnOnce() -> Result<F, SynthesisError>,
36        A: FnOnce() -> AR,
37        AR: AsRef<str>,
38    {
39        self.0.alloc(annotation, f)
40    }
41
42    #[inline]
43    fn alloc_input<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
44    where
45        FN: FnOnce() -> Result<F, SynthesisError>,
46        A: FnOnce() -> AR,
47        AR: AsRef<str>,
48    {
49        self.0.alloc_input(annotation, f)
50    }
51
52    #[inline]
53    fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
54    where
55        A: FnOnce() -> AR,
56        AR: AsRef<str>,
57        LA: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
58        LB: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
59        LC: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
60    {
61        self.0.enforce(annotation, a, b, c)
62    }
63
64    // Downstream users who use `namespace` will never interact with these
65    // functions and they will never be invoked because the namespace is
66    // never a root constraint system.
67
68    #[inline]
69    fn push_namespace<NR, N>(&mut self, _: N)
70    where
71        NR: AsRef<str>,
72        N: FnOnce() -> NR,
73    {
74        panic!("only the root's push_namespace should be called");
75    }
76
77    #[inline]
78    fn pop_namespace(&mut self) {
79        panic!("only the root's pop_namespace should be called");
80    }
81
82    #[inline]
83    fn get_root(&mut self) -> &mut Self::Root {
84        self.0.get_root()
85    }
86
87    #[inline]
88    fn num_constraints(&self) -> usize {
89        self.0.num_constraints()
90    }
91
92    #[inline]
93    fn num_public_variables(&self) -> usize {
94        self.0.num_public_variables()
95    }
96
97    #[inline]
98    fn num_private_variables(&self) -> usize {
99        self.0.num_private_variables()
100    }
101
102    #[inline]
103    fn is_in_setup_mode(&self) -> bool {
104        self.0.is_in_setup_mode()
105    }
106}
107
108impl<F: Field, CS: ConstraintSystem<F>> Drop for Namespace<'_, F, CS> {
109    #[inline]
110    fn drop(&mut self) {
111        self.get_root().pop_namespace()
112    }
113}