1use mina_curves::pasta::Fp;
2use mina_signer::CompressedPubKey;
3
4use crate::{
5 checked_equal_compressed_key,
6 proofs::{
7 field::{field, Boolean, ToBoolean},
8 numbers::common::ForZkappCheck,
9 witness::Witness,
10 },
11 scan_state::transaction_logic::zkapp_command::{ClosedInterval, OrIgnore},
12 MyCow,
13};
14
15pub trait ZkappCheck {
17 type T;
18
19 fn zcheck<Ops: ZkappCheckOps>(&self, x: &Self::T, w: &mut Witness<Fp>) -> Boolean;
20}
21
22impl<T> OrIgnore<T> {
23 fn make_zcheck<Ops, CompareFn, DefaultFn>(
24 &self,
25 default_fn: CompareFn,
26 compare_fun: DefaultFn,
27 w: &mut Witness<Fp>,
28 ) -> Boolean
29 where
30 Ops: ZkappCheckOps,
31 CompareFn: Fn() -> T,
32 DefaultFn: Fn(&T, &mut Witness<Fp>) -> Boolean,
33 {
34 let (is_some, value) = match self {
35 OrIgnore::Check(v) => (Boolean::True, MyCow::Borrow(v)),
36 OrIgnore::Ignore => (Boolean::False, MyCow::Own(default_fn())),
37 };
38 let is_good = compare_fun(value.as_ref(), w);
39 Ops::boolean_any([is_some.neg(), is_good], w)
40 }
41}
42
43impl<DefaultFn> ZkappCheck for (&OrIgnore<Boolean>, DefaultFn)
44where
45 DefaultFn: Fn() -> Boolean,
46{
47 type T = Boolean;
48
49 fn zcheck<Ops: ZkappCheckOps>(&self, x: &Self::T, w: &mut Witness<Fp>) -> Boolean {
50 let (this, default_fn) = self;
51 let compare = |value: &Self::T, w: &mut Witness<Fp>| Ops::is_boolean_equal(x, value, w);
52 this.make_zcheck::<Ops, _, _>(default_fn, compare, w)
53 }
54}
55
56impl<DefaultFn> ZkappCheck for (&OrIgnore<Fp>, DefaultFn)
57where
58 DefaultFn: Fn() -> Fp,
59{
60 type T = Fp;
61
62 fn zcheck<Ops: ZkappCheckOps>(&self, x: &Self::T, w: &mut Witness<Fp>) -> Boolean {
63 let (this, default_fn) = self;
64 let compare = |value: &Self::T, w: &mut Witness<Fp>| Ops::is_field_equal(x, value, w);
65 this.make_zcheck::<Ops, _, _>(default_fn, compare, w)
66 }
67}
68
69impl<DefaultFn> ZkappCheck for (&OrIgnore<CompressedPubKey>, DefaultFn)
70where
71 DefaultFn: Fn() -> CompressedPubKey,
72{
73 type T = CompressedPubKey;
74
75 fn zcheck<Ops: ZkappCheckOps>(&self, x: &Self::T, w: &mut Witness<Fp>) -> Boolean {
76 let (this, default_fn) = self;
77 let compare =
78 |value: &Self::T, w: &mut Witness<Fp>| Ops::is_compressed_key_equal(x, value, w);
79 this.make_zcheck::<Ops, _, _>(default_fn, compare, w)
80 }
81}
82
83impl<T, DefaultFn> ZkappCheck for (&OrIgnore<ClosedInterval<T>>, DefaultFn)
84where
85 DefaultFn: Fn() -> ClosedInterval<T>,
86 T: ForZkappCheck<Fp>,
87{
88 type T = T;
89
90 fn zcheck<Ops: ZkappCheckOps>(&self, x: &Self::T, w: &mut Witness<Fp>) -> Boolean {
91 let (this, default_fn) = self;
92 let compare = |value: &ClosedInterval<T>, w: &mut Witness<Fp>| {
93 Ops::compare_closed_interval(value, x, w)
94 };
95 this.make_zcheck::<Ops, _, _>(default_fn, compare, w)
96 }
97}
98
99pub trait ZkappCheckOps {
100 fn compare_closed_interval<T: ForZkappCheck<Fp>>(
101 interval: &ClosedInterval<T>,
102 value: &T,
103 w: &mut Witness<Fp>,
104 ) -> Boolean;
105 fn is_boolean_equal(a: &Boolean, b: &Boolean, w: &mut Witness<Fp>) -> Boolean;
106 fn is_field_equal(a: &Fp, b: &Fp, w: &mut Witness<Fp>) -> Boolean;
107 fn is_compressed_key_equal(
108 a: &CompressedPubKey,
109 b: &CompressedPubKey,
110 w: &mut Witness<Fp>,
111 ) -> Boolean;
112 fn boolean_all<I>(bools: I, w: &mut Witness<Fp>) -> Boolean
113 where
114 I: IntoIterator<Item = Boolean>;
115 fn boolean_any<I>(bools: I, w: &mut Witness<Fp>) -> Boolean
116 where
117 I: IntoIterator<Item = Boolean>;
118}
119
120pub struct InSnarkOps;
121pub struct NonSnarkOps;
122
123impl ZkappCheckOps for InSnarkOps {
124 fn compare_closed_interval<T: ForZkappCheck<Fp>>(
125 interval: &ClosedInterval<T>,
126 value: &T,
127 w: &mut Witness<Fp>,
128 ) -> Boolean {
129 let ClosedInterval { lower, upper } = interval;
130 let lower = lower.to_checked();
131 let upper = upper.to_checked();
132 let x = value.to_checked();
133 let lower_than_upper = <T as ForZkappCheck<Fp>>::lte(&x, &upper, w);
135 let greater_than_lower = <T as ForZkappCheck<Fp>>::lte(&lower, &x, w);
136 Boolean::all(&[greater_than_lower, lower_than_upper], w)
137 }
138 fn is_boolean_equal(a: &Boolean, b: &Boolean, w: &mut Witness<Fp>) -> Boolean {
139 Boolean::equal(a, b, w)
140 }
141 fn is_field_equal(a: &Fp, b: &Fp, w: &mut Witness<Fp>) -> Boolean {
142 field::equal(*a, *b, w)
143 }
144 fn is_compressed_key_equal(
145 a: &CompressedPubKey,
146 b: &CompressedPubKey,
147 w: &mut Witness<Fp>,
148 ) -> Boolean {
149 checked_equal_compressed_key(a, b, w)
150 }
151 fn boolean_all<I>(bools: I, w: &mut Witness<Fp>) -> Boolean
152 where
153 I: IntoIterator<Item = Boolean>,
154 {
155 let bools = bools.into_iter().collect::<Vec<_>>();
156 Boolean::all(&bools, w)
157 }
158 fn boolean_any<I>(bools: I, w: &mut Witness<Fp>) -> Boolean
159 where
160 I: IntoIterator<Item = Boolean>,
161 {
162 let bools = bools.into_iter().collect::<Vec<_>>();
163 Boolean::any(&bools, w)
164 }
165}
166
167impl ZkappCheckOps for NonSnarkOps {
168 fn compare_closed_interval<T: ForZkappCheck<Fp>>(
169 interval: &ClosedInterval<T>,
170 value: &T,
171 _w: &mut Witness<Fp>,
172 ) -> Boolean {
173 let ClosedInterval { lower, upper } = interval;
174 (lower <= value && value <= upper).to_boolean()
175 }
176 fn is_boolean_equal(a: &Boolean, b: &Boolean, _w: &mut Witness<Fp>) -> Boolean {
177 (a == b).to_boolean()
178 }
179 fn is_field_equal(a: &Fp, b: &Fp, _w: &mut Witness<Fp>) -> Boolean {
180 (a == b).to_boolean()
181 }
182 fn is_compressed_key_equal(
183 a: &CompressedPubKey,
184 b: &CompressedPubKey,
185 _w: &mut Witness<Fp>,
186 ) -> Boolean {
187 (a == b).to_boolean()
188 }
189 fn boolean_all<I>(bools: I, _w: &mut Witness<Fp>) -> Boolean
190 where
191 I: IntoIterator<Item = Boolean>,
192 {
193 bools.into_iter().all(|b| b.as_bool()).to_boolean()
194 }
195 fn boolean_any<I>(bools: I, _w: &mut Witness<Fp>) -> Boolean
196 where
197 I: IntoIterator<Item = Boolean>,
198 {
199 bools.into_iter().any(|b| b.as_bool()).to_boolean()
200 }
201}