rsnark_core/
circuit.rs

1use num::BigInt;
2
3use crate::{API, VariableIniter, variable::CircuitVariable};
4
5/// Defines the logic of an arithmetic circuit for zero-knowledge proofs.
6///
7/// This trait should be implemented by circuit structures to define their
8/// constraint system. The circuit logic is expressed using the provided API
9/// operations to build the constraint graph.
10pub trait Circuit {
11    fn define(&self, api: &mut impl API);
12}
13
14/// Defines a circuit with witness data structure.
15///
16/// This trait represents the witness data that corresponds to a `CircuitElement`.
17/// While `CircuitElement` defines the structure used in circuit logic,
18/// `CircuitWitness` contains the actual values used during proof generation.
19///
20/// This trait should not be implemented manually. Instead, use the
21/// `#[circuit]` macro to automatically generate the implementation.
22pub trait CircuitWitness: CircuitPublicWitness {
23    type CircuitElement: CircuitElement<CircuitWitness = Self>;
24    /// The type representing the public witness for this circuit.
25    type PublicWitness: CircuitPublicWitness;
26
27    #[doc(hidden)]
28    fn create_public(initer: &mut VariableIniter, is_private: bool) -> Self::CircuitElement;
29
30    #[doc(hidden)]
31    fn create_private(initer: &mut VariableIniter) -> Self::CircuitElement;
32
33    /// Converts this circuit witness into its public witness representation.
34    ///
35    /// This extracts only the public portion of the witness, which is
36    /// needed for verification in zero-knowledge proof systems.
37    ///
38    /// # Returns
39    /// The public witness containing only public inputs
40    fn into_public_witness(self) -> Self::PublicWitness;
41
42    #[doc(hidden)]
43    fn append_witness(&self, public: &mut Vec<BigInt>, private: &mut Vec<BigInt>, is_private: bool);
44}
45
46/// Represents a circuit element that can be used in circuit construction.
47///
48/// This trait establishes the relationship between circuit elements and their
49/// corresponding witness data.
50///
51/// # Implementation
52///
53/// This trait should **not** be implemented manually. Instead, it is automatically
54/// implemented when using the `#[circuit]` attribute macro.
55pub trait CircuitElement {
56    /// The witness type associated with this circuit element.
57    type CircuitWitness: CircuitWitness;
58}
59
60/// Represents the public witness portion of a circuit.
61///
62/// This trait should not be implemented manually. Instead, use the
63/// `#[circuit]` macro to automatically generate the implementation.
64/// It handles serialization of public inputs for the circuit.
65pub trait CircuitPublicWitness {
66    fn append_public_witness(&self, witness: &mut Vec<BigInt>, is_private: bool);
67}
68
69/// Represents the witness portion of a circuit.
70pub type Witness<T> = <T as CircuitElement>::CircuitWitness;
71
72/// Represents the public witness portion of a circuit.
73pub type PublicWitness<T> =
74    <<T as CircuitElement>::CircuitWitness as CircuitWitness>::PublicWitness;
75
76#[doc(hidden)]
77pub type CircuitElementInner<T> =
78    <<T as CircuitElement>::CircuitWitness as CircuitWitness>::CircuitElement;
79
80macro_rules! define_circuit_element_for_from_u256 {
81    ($t:ty) => {
82        impl CircuitWitness for $t {
83            type CircuitElement = CircuitVariable<$t>;
84            type PublicWitness = $t;
85
86            fn create_public(
87                initer: &mut VariableIniter,
88                is_private: bool,
89            ) -> Self::CircuitElement {
90                initer.new_public(is_private).into()
91            }
92
93            fn create_private(initer: &mut VariableIniter) -> Self::CircuitElement {
94                initer.new_private().into()
95            }
96
97            fn into_public_witness(self) -> Self::PublicWitness {
98                self
99            }
100
101            fn append_witness(
102                &self,
103                public: &mut Vec<BigInt>,
104                private: &mut Vec<BigInt>,
105                is_private: bool,
106            ) {
107                let x = BigInt::from(*self);
108                if is_private {
109                    private.push(x);
110                } else {
111                    public.push(x);
112                }
113            }
114        }
115
116        impl CircuitPublicWitness for $t {
117            fn append_public_witness(&self, witness: &mut Vec<BigInt>, is_private: bool) {
118                let x = BigInt::from(*self);
119                if !is_private {
120                    witness.push(x);
121                }
122            }
123        }
124
125        impl CircuitElement for CircuitVariable<$t> {
126            type CircuitWitness = $t;
127        }
128
129        impl CircuitElement for $t {
130            type CircuitWitness = $t;
131        }
132    };
133}
134
135define_circuit_element_for_from_u256!(u128);
136define_circuit_element_for_from_u256!(u64);
137define_circuit_element_for_from_u256!(u32);
138define_circuit_element_for_from_u256!(u16);
139define_circuit_element_for_from_u256!(u8);
140define_circuit_element_for_from_u256!(i128);
141define_circuit_element_for_from_u256!(i64);
142define_circuit_element_for_from_u256!(i32);
143define_circuit_element_for_from_u256!(i16);
144define_circuit_element_for_from_u256!(i8);
145define_circuit_element_for_from_u256!(bool);