snarkvm_algorithms/r1cs/
namespace.rs

1// Copyright 2024 Aleo Network Foundation
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::r1cs::{ConstraintSystem, LinearCombination, Variable, errors::SynthesisError};
17use snarkvm_fields::Field;
18
19use std::marker::PhantomData;
20
21/// This is a "namespaced" constraint system which borrows a constraint system
22/// (pushing a namespace context) and, when dropped, pops out of the namespace context.
23pub struct Namespace<'a, F: Field, CS: ConstraintSystem<F>>(pub(super) &'a mut CS, pub(super) PhantomData<F>);
24
25impl<F: Field, CS: ConstraintSystem<F>> ConstraintSystem<F> for Namespace<'_, F, CS> {
26    type Root = CS::Root;
27
28    #[inline]
29    fn one() -> Variable {
30        CS::one()
31    }
32
33    #[inline]
34    fn alloc<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
35    where
36        FN: FnOnce() -> Result<F, SynthesisError>,
37        A: FnOnce() -> AR,
38        AR: AsRef<str>,
39    {
40        self.0.alloc(annotation, f)
41    }
42
43    #[inline]
44    fn alloc_input<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
45    where
46        FN: FnOnce() -> Result<F, SynthesisError>,
47        A: FnOnce() -> AR,
48        AR: AsRef<str>,
49    {
50        self.0.alloc_input(annotation, f)
51    }
52
53    #[inline]
54    fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
55    where
56        A: FnOnce() -> AR,
57        AR: AsRef<str>,
58        LA: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
59        LB: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
60        LC: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
61    {
62        self.0.enforce(annotation, a, b, c)
63    }
64
65    // Downstream users who use `namespace` will never interact with these
66    // functions and they will never be invoked because the namespace is
67    // never a root constraint system.
68
69    #[inline]
70    fn push_namespace<NR, N>(&mut self, _: N)
71    where
72        NR: AsRef<str>,
73        N: FnOnce() -> NR,
74    {
75        panic!("only the root's push_namespace should be called");
76    }
77
78    #[inline]
79    fn pop_namespace(&mut self) {
80        panic!("only the root's pop_namespace should be called");
81    }
82
83    #[inline]
84    fn get_root(&mut self) -> &mut Self::Root {
85        self.0.get_root()
86    }
87
88    #[inline]
89    fn num_constraints(&self) -> usize {
90        self.0.num_constraints()
91    }
92
93    #[inline]
94    fn num_public_variables(&self) -> usize {
95        self.0.num_public_variables()
96    }
97
98    #[inline]
99    fn num_private_variables(&self) -> usize {
100        self.0.num_private_variables()
101    }
102
103    #[inline]
104    fn is_in_setup_mode(&self) -> bool {
105        self.0.is_in_setup_mode()
106    }
107}
108
109impl<F: Field, CS: ConstraintSystem<F>> Drop for Namespace<'_, F, CS> {
110    #[inline]
111    fn drop(&mut self) {
112        self.get_root().pop_namespace()
113    }
114}