Skip to main content

midnight_circuits/instructions/
assignments.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
14//! Assignment instructions interface.
15//!
16//! It provides functions for assigning fixed and secret values into the
17//! circuit.
18//!
19//! This trait is parametrized by the resulting `Assigned` type (a generic of
20//! this trait that implements [InnerValue]). The assignment functions take an
21//! `Assigned::Element` as input and return an `Assigned` value.
22
23use ff::PrimeField;
24use midnight_proofs::{
25    circuit::{Layouter, Value},
26    plonk::Error,
27};
28
29use crate::types::InnerValue;
30
31/// The set of circuit instructions for assignment operations.
32pub trait AssignmentInstructions<F, Assigned>
33where
34    F: PrimeField,
35    Assigned: InnerValue,
36{
37    /// Assigns an element as a private input to the circuit.
38    ///
39    /// In the following example, `chip` implements [AssignmentInstructions] for
40    /// [AssignedNative](crate::types::AssignedNative).
41    ///
42    /// ```
43    /// # midnight_circuits::run_test_native_gadget!(chip, layouter, {
44    /// // we load a secret variable into the circuit, only the prover may know its value
45    /// let x: AssignedNative<F> = chip.assign(&mut layouter, Value::known(F::ZERO))?;
46    /// # });
47    /// ```
48    ///
49    /// But `chip` can also implement [AssignmentInstructions] for
50    /// [AssignedBit](crate::types::AssignedBit) or
51    /// [AssignedByte](crate::types::AssignedByte) and other types.
52    ///
53    /// ```
54    /// # midnight_circuits::run_test_native_gadget!(chip, layouter, {
55    /// let bit: AssignedBit<F> = chip.assign(&mut layouter, Value::known(true))?;
56    ///
57    /// let byte: AssignedByte<F> = chip.assign(&mut layouter, Value::known(42u8))?;
58    /// # });
59    /// ```
60    fn assign(
61        &self,
62        layouter: &mut impl Layouter<F>,
63        value: Value<Assigned::Element>,
64    ) -> Result<Assigned, Error>;
65
66    /// Assigns a fixed (constant) element.
67    ///
68    /// ```
69    /// # midnight_circuits::run_test_native_gadget!(chip, layouter, {
70    /// // we load a constant into the circuit, everyone knows the value of `k`
71    /// let x: AssignedNative<F> = chip.assign_fixed(&mut layouter, F::ONE)?;
72    ///
73    /// // we can also assign fixed bits or bytes if the chip supports these types
74    /// let bit: AssignedBit<F> = chip.assign_fixed(&mut layouter, false)?;
75    /// let byte: AssignedByte<F> = chip.assign_fixed(&mut layouter, 255u8)?;
76    /// # });
77    /// ```
78    fn assign_fixed(
79        &self,
80        layouter: &mut impl Layouter<F>,
81        constant: Assigned::Element,
82    ) -> Result<Assigned, Error>;
83
84    /// Assigns several elements as private inputs to the circuit.
85    ///
86    /// This is potentially more efficient than calling
87    /// [assign](AssignmentInstructions::assign) multiple times.
88    fn assign_many(
89        &self,
90        layouter: &mut impl Layouter<F>,
91        values: &[Value<Assigned::Element>],
92    ) -> Result<Vec<Assigned>, Error> {
93        values
94            .iter()
95            .map(|v| self.assign(layouter, v.clone()))
96            .collect::<Result<Vec<Assigned>, Error>>()
97    }
98
99    /// Assigns several elements fixed values to the circuit.
100    ///
101    /// This is potentially more efficient than calling
102    /// [assign_fixed](AssignmentInstructions::assign_fixed) multiple times.
103    fn assign_many_fixed(
104        &self,
105        layouter: &mut impl Layouter<F>,
106        values: &[Assigned::Element],
107    ) -> Result<Vec<Assigned>, Error> {
108        values
109            .iter()
110            .map(|v| self.assign_fixed(layouter, v.clone()))
111            .collect::<Result<Vec<Assigned>, Error>>()
112    }
113}