Skip to main content

midnight_circuits/utils/
types.rs

1// This file is part of MIDNIGHT-ZK.
2// Copyright (C) Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
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// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14use core::fmt::Debug;
15
16use midnight_proofs::circuit::Value;
17#[cfg(any(test, feature = "testing"))]
18use rand::RngCore;
19
20use crate::{field::AssignedNative, CircuitField};
21
22/// Trait for dealing with public inputs. `Instantiable` is implemented on
23/// off-circuit types to determine the way these types are transformed into
24/// vectors of native values.
25/// Analogous functions exists for constraining public inputs in-circuit in
26/// the [crate::instructions::PublicInputInstructions] trait.
27pub trait Instantiable<F: CircuitField>: InnerValue {
28    /// This function is the off-circuit analog of
29    /// [crate::instructions::PublicInputInstructions::as_public_input].
30    fn as_public_input(element: &<Self as InnerValue>::Element) -> Vec<F>;
31
32    /// Inverse of [Self::as_public_input]: reconstructs the element from
33    /// its public input representation. Returns `None` if `fields` does not
34    /// encode a valid element.
35    fn from_public_input(fields: &[F]) -> Option<<Self as InnerValue>::Element>;
36}
37
38/// Trait for accessing the value inside assigned circuit elements.
39pub trait InnerValue: Clone + Debug {
40    /// Represents the unassigned type corresponding to the [InnerValue]
41    type Element: Clone + Debug;
42
43    /// Returns the value of the assigned element.
44    fn value(&self) -> Value<Self::Element>;
45}
46
47impl<T: InnerValue, const L: usize> InnerValue for [T; L] {
48    type Element = [T::Element; L];
49
50    fn value(&self) -> Value<Self::Element> {
51        let val = Value::from_iter(self.iter().map(|val| val.value()));
52        // We know sizes will match due to the type system. The problem is
53        // that the type Value is not right enough.
54        val.map(|v: Vec<T::Element>| v.try_into().unwrap())
55    }
56}
57
58/// Trait for accessing constant values of the inner value type of an assigned
59/// element.
60pub trait InnerConstants: InnerValue {
61    /// The zero of Self::Element (additive identity).
62    fn inner_zero() -> Self::Element;
63
64    /// The unit of Self::Element (multiplicative identity and/or additive
65    /// generator).
66    fn inner_one() -> Self::Element;
67}
68
69impl<F: CircuitField> Instantiable<F> for AssignedNative<F> {
70    fn as_public_input(element: &F) -> Vec<F> {
71        vec![*element]
72    }
73
74    fn from_public_input(fields: &[F]) -> Option<F> {
75        match fields {
76            [f] => Some(*f),
77            _ => None,
78        }
79    }
80}
81
82impl<F: CircuitField> InnerValue for AssignedNative<F> {
83    type Element = F;
84
85    fn value(&self) -> Value<F> {
86        self.value().cloned()
87    }
88}
89
90impl<F: CircuitField> InnerConstants for AssignedNative<F> {
91    fn inner_zero() -> F {
92        F::ZERO
93    }
94
95    fn inner_one() -> F {
96        F::ONE
97    }
98}
99
100#[cfg(any(test, feature = "testing"))]
101/// A trait for types that can be inverted. This should only
102/// be used for testing.
103pub trait Invertible {
104    /// Returns the multiplicative inverse of the given value.
105    ///
106    /// # Panics
107    ///
108    /// If the given value does not have an inverse.
109    fn invert(&self) -> Self;
110}
111
112#[cfg(any(test, feature = "testing"))]
113impl<F: CircuitField> Invertible for F {
114    fn invert(&self) -> F {
115        self.invert().unwrap()
116    }
117}
118
119#[cfg(any(test, feature = "testing"))]
120/// A trait for types that can be sampled at random. This should only
121/// be used for testing.
122pub trait Sampleable: InnerValue {
123    /// Returns a random inner element, given a random number generator.
124    fn sample_inner(rng: impl RngCore) -> Self::Element;
125}
126
127#[cfg(any(test, feature = "testing"))]
128impl<F: CircuitField> Sampleable for AssignedNative<F> {
129    fn sample_inner(rng: impl RngCore) -> F {
130        F::random(rng)
131    }
132}