snarkvm_synthesizer_process/trace/inclusion/assignment_v0.rs
1// Copyright (c) 2019-2025 Provable Inc.
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 super::*;
17
18#[derive(Clone, Debug)]
19pub struct InclusionV0Assignment<N: Network> {
20 pub(crate) state_path: StatePath<N>,
21 commitment: Field<N>,
22 gamma: Group<N>,
23 serial_number: Field<N>,
24 local_state_root: N::TransactionID,
25 is_global: bool,
26}
27
28impl<N: Network> InclusionV0Assignment<N> {
29 /// Initializes a new inclusion assignment.
30 pub fn new(
31 state_path: StatePath<N>,
32 commitment: Field<N>,
33 gamma: Group<N>,
34 serial_number: Field<N>,
35 local_state_root: N::TransactionID,
36 is_global: bool,
37 ) -> Self {
38 Self { state_path, commitment, gamma, serial_number, local_state_root, is_global }
39 }
40
41 /// The circuit for state path verification.
42 ///
43 /// # Diagram
44 /// The `[[ ]]` notation is used to denote public inputs.
45 /// ```ignore
46 /// [[ global_state_root ]] || [[ local_state_root ]]
47 /// | |
48 /// -------- is_global --------
49 /// |
50 /// state_path
51 /// |
52 /// [[ serial_number ]] := Commit( commitment || Hash( COFACTOR * gamma ) )
53 /// ```
54 pub fn to_circuit_assignment<A: circuit::Aleo<Network = N>>(&self) -> Result<circuit::Assignment<N::Field>> {
55 use circuit::Inject;
56
57 // Ensure the circuit environment is clean.
58 assert_eq!(A::count(), (0, 1, 0, 0, (0, 0, 0)));
59 A::reset();
60
61 // Inject the state path as `Mode::Private` (with a global state root as `Mode::Public`).
62 let state_path = circuit::StatePath::<A>::new(circuit::Mode::Private, self.state_path.clone());
63 // Inject the commitment as `Mode::Private`.
64 let commitment = circuit::Field::<A>::new(circuit::Mode::Private, self.commitment);
65 // Inject the gamma as `Mode::Private`.
66 let gamma = circuit::Group::<A>::new(circuit::Mode::Private, self.gamma);
67
68 // Inject the local state root as `Mode::Public`.
69 let local_state_root = circuit::Field::<A>::new(circuit::Mode::Public, *self.local_state_root);
70 // Inject the 'is_global' flag as `Mode::Private`.
71 let is_global = circuit::Boolean::<A>::new(circuit::Mode::Private, self.is_global);
72
73 // Inject the serial number as `Mode::Public`.
74 let serial_number = circuit::Field::<A>::new(circuit::Mode::Public, self.serial_number);
75 // Compute the candidate serial number.
76 let candidate_serial_number =
77 circuit::Record::<A, circuit::Plaintext<A>>::serial_number_from_gamma(&gamma, commitment.clone());
78 // Enforce that the candidate serial number is equal to the serial number.
79 A::assert_eq(candidate_serial_number, serial_number);
80
81 // Enforce the starting leaf is the claimed commitment.
82 A::assert_eq(state_path.transition_leaf().id(), commitment);
83 // Enforce the state path from leaf to root is correct.
84 A::assert(state_path.verify(&is_global, &local_state_root));
85
86 Stack::log_circuit::<A>(format_args!("State Path for {}", self.serial_number));
87
88 // Eject the assignment and reset the circuit environment.
89 Ok(A::eject_assignment_and_reset())
90 }
91}