snarkvm_algorithms/r1cs/
namespace.rs

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