Skip to main content

midnight_circuits/utils/
types.rs

1// This file is part of MIDNIGHT-ZK.
2// Copyright (C) 2025 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;
15use std::ops::{Add, Neg};
16
17use ff::PrimeField;
18use midnight_proofs::circuit::Value;
19use num_bigint::BigUint;
20#[cfg(any(test, feature = "testing"))]
21use rand::RngCore;
22
23use crate::{
24    types::AssignedNative,
25    utils::util::{big_to_fe, fe_to_big},
26};
27
28/// Trait for dealing with public inputs. `Instantiable` is implemented on
29/// off-circuit types to determine the way these types are transformed into
30/// vectors of native values.
31/// Analogous functions exists for constraining public inputs in-circuit in
32/// the [crate::instructions::PublicInputInstructions] trait.
33pub trait Instantiable<F: PrimeField>: InnerValue {
34    /// This function is the off-circuit analog of
35    /// [crate::instructions::PublicInputInstructions::as_public_input].
36    fn as_public_input(element: &<Self as InnerValue>::Element) -> Vec<F>;
37
38    /// Inverse of [Self::as_public_input]: reconstructs the element from
39    /// its public input representation. Returns `None` if `fields` does not
40    /// encode a valid element.
41    fn from_public_input(fields: &[F]) -> Option<<Self as InnerValue>::Element>;
42}
43
44/// Trait for accessing the value inside assigned circuit elements.
45pub trait InnerValue: Clone + Debug {
46    /// Represents the unassigned type corresponding to the [InnerValue]
47    type Element: Clone + Debug;
48
49    /// Returns the value of the assigned element.
50    fn value(&self) -> Value<Self::Element>;
51}
52
53impl<T: InnerValue, const L: usize> InnerValue for [T; L] {
54    type Element = [T::Element; L];
55
56    fn value(&self) -> Value<Self::Element> {
57        let val = Value::from_iter(self.iter().map(|val| val.value()));
58        // We know sizes will match due to the type system. The problem is
59        // that the type Value is not right enough.
60        val.map(|v: Vec<T::Element>| v.try_into().unwrap())
61    }
62}
63
64/// Trait for accessing constant values of the inner value type of an assigned
65/// element.
66pub trait InnerConstants: InnerValue {
67    /// The zero of Self::Element (additive identity).
68    fn inner_zero() -> Self::Element;
69
70    /// The unit of Self::Element (multiplicative identity and/or additive
71    /// generator).
72    fn inner_one() -> Self::Element;
73}
74
75impl<F: PrimeField> Instantiable<F> for AssignedNative<F> {
76    fn as_public_input(element: &F) -> Vec<F> {
77        vec![*element]
78    }
79
80    fn from_public_input(fields: &[F]) -> Option<F> {
81        match fields {
82            [f] => Some(*f),
83            _ => None,
84        }
85    }
86}
87
88impl<F: PrimeField> InnerValue for AssignedNative<F> {
89    type Element = F;
90
91    fn value(&self) -> Value<F> {
92        self.value().cloned()
93    }
94}
95
96impl<F: PrimeField> InnerConstants for AssignedNative<F> {
97    fn inner_zero() -> F {
98        F::ZERO
99    }
100
101    fn inner_one() -> F {
102        F::ONE
103    }
104}
105
106/// A trait for types that can be converted from and into BigUint.
107pub trait FromBigUint: PartialEq + From<u64> + Add<Output = Self> + Neg<Output = Self> {
108    /// Conversion from BigUint.
109    fn from_biguint(x: BigUint) -> Self;
110
111    /// Convertion into BigUint.
112    fn into_biguint(self) -> BigUint;
113}
114
115impl<F: PrimeField> FromBigUint for F {
116    fn from_biguint(x: BigUint) -> Self {
117        big_to_fe(x)
118    }
119
120    fn into_biguint(self) -> BigUint {
121        fe_to_big(self)
122    }
123}
124
125#[cfg(any(test, feature = "testing"))]
126/// A trait for types that can be inverted. This should only
127/// be used for testing.
128pub trait Invertible {
129    /// Returns the multiplicative inverse of the given value.
130    ///
131    /// # Panics
132    ///
133    /// If the given value does not have an inverse.
134    fn invert(&self) -> Self;
135}
136
137#[cfg(any(test, feature = "testing"))]
138impl<F: PrimeField> Invertible for F {
139    fn invert(&self) -> F {
140        self.invert().unwrap()
141    }
142}
143
144#[cfg(any(test, feature = "testing"))]
145/// A trait for types that can be sampled at random. This should only
146/// be used for testing.
147pub trait Sampleable: InnerValue {
148    /// Returns a random inner element, given a random number generator.
149    fn sample_inner(rng: impl RngCore) -> Self::Element;
150}
151
152#[cfg(any(test, feature = "testing"))]
153impl<F: PrimeField> Sampleable for AssignedNative<F> {
154    fn sample_inner(rng: impl RngCore) -> F {
155        F::random(rng)
156    }
157}