1#![allow(unused)]
2
3use std::marker::PhantomData;
4
5use mina_curves::pasta::Fp;
6use mina_signer::CompressedPubKey;
7
8use crate::{
9 check_permission,
10 proofs::{
11 field::{Boolean, FieldWitness, ToBoolean},
12 to_field_elements::ToFieldElements,
13 transaction::Check,
14 witness::Witness,
15 zkapp::StartDataSkeleton,
16 },
17 scan_state::{
18 currency::{Amount, Balance, Index, Magnitude, Signed, Slot, SlotSpan, TxnVersion},
19 transaction_logic::{
20 account_check_timing,
21 local_state::{CallStack, StackFrame},
22 protocol_state::GlobalStateSkeleton,
23 set_with_location,
24 zkapp_command::{
25 self, AccountPreconditions, AccountUpdate, CallForest, CheckAuthorizationResult,
26 SetOrKeep,
27 },
28 zkapp_statement::TransactionCommitment,
29 ExistingOrNew, TimingValidation, TransactionFailure,
30 },
31 },
32 sparse_ledger::{LedgerIntf, SparseLedger},
33 zkapps::checks::ZkappCheck,
34 Account, AccountId, AuthRequired, ControlTag, Mask, MyCow, TokenId, ZkAppAccount,
35 TXN_VERSION_CURRENT,
36};
37
38use super::{
39 checks::NonSnarkOps,
40 intefaces::{
41 AccountIdInterface, AccountInterface, AccountUpdateInterface, ActionsInterface,
42 AmountInterface, BalanceInterface, BoolInterface, BranchEvaluation, BranchInterface,
43 BranchParam, CallForestInterface, CallStackInterface, ControllerInterface,
44 GlobalSlotSinceGenesisInterface, GlobalSlotSpanInterface, GlobalStateInterface,
45 IndexInterface, LedgerInterface, LocalStateInterface, Opt, ReceiptChainHashInterface,
46 SetOrKeepInterface, SignedAmountBranchParam, SignedAmountInterface, StackFrameInterface,
47 StackFrameMakeParams, StackInterface, TokenIdInterface, TransactionCommitmentInterface,
48 TxnVersionInterface, VerificationKeyHashInterface, WitnessGenerator, ZkappApplication,
49 ZkappHandler,
50 },
51 zkapp_logic::{self, ApplyZkappParams, ZkAppCommandElt},
52};
53
54pub type GlobalStateForNonSnark<L> = GlobalStateSkeleton<
55 L, Signed<Amount>, Slot, >;
59
60type NonSnarkVerificationKeyHash = Option<Fp>;
61pub struct NonSnarkController;
62pub struct NonSnarkSetOrKeep;
63pub struct NonSnarkGlobalSlotSpan;
64pub struct NonSnarkActions;
65pub struct NonSnarkReceiptChainHash;
66pub struct NonSnarkHandler<L>(PhantomData<L>);
67
68#[derive(Clone, Debug)]
69pub struct ZkappNonSnark<L>(PhantomData<L>);
70
71pub trait LedgerNonSnark
73where
74 Self: LedgerInterface<W = (), AccountUpdate = AccountUpdate, Account = Account, Bool = bool>,
75{
76}
77impl<T> LedgerNonSnark for T where
78 T: LedgerInterface<W = (), AccountUpdate = AccountUpdate, Account = Account, Bool = bool>
79{
80}
81
82impl<L: LedgerNonSnark> ZkappApplication for ZkappNonSnark<L> {
83 type Ledger = L;
84 type SignedAmount = Signed<Amount>;
85 type Amount = Amount;
86 type Balance = Balance;
87 type Index = Index;
88 type GlobalSlotSinceGenesis = Slot;
89 type StackFrame = StackFrame;
90 type CallForest = CallForest<AccountUpdate>;
91 type CallStack = CallStack;
92 type GlobalState = GlobalStateForNonSnark<L>;
93 type AccountUpdate = AccountUpdate;
94 type AccountId = AccountId;
95 type TokenId = TokenId;
96 type Bool = bool;
97 type TransactionCommitment = TransactionCommitment;
98 type FailureStatusTable = Vec<Vec<TransactionFailure>>;
99 type LocalState = zkapp_logic::LocalState<Self>;
100 type Account = Account;
101 type VerificationKeyHash = NonSnarkVerificationKeyHash;
102 type SingleData = ();
103 type Controller = NonSnarkController;
104 type TxnVersion = TxnVersion;
105 type SetOrKeep = NonSnarkSetOrKeep;
106 type GlobalSlotSpan = NonSnarkGlobalSlotSpan;
107 type Actions = NonSnarkActions;
108 type ReceiptChainHash = NonSnarkReceiptChainHash;
109 type Handler = NonSnarkHandler<L>;
110 type Branch = NonSnarkBranch;
111 type WitnessGenerator = ();
112}
113
114impl<F: FieldWitness> WitnessGenerator<F> for () {
115 type Bool = bool;
116
117 fn exists<T>(&mut self, data: T) -> T
118 where
119 T: ToFieldElements<F> + Check<F>,
120 {
121 data
122 }
123 fn exists_no_check<T>(&mut self, data: T) -> T
124 where
125 T: ToFieldElements<F>,
126 {
127 data
128 }
129 fn exists_no_check_on_bool<T>(&mut self, _b: Self::Bool, data: T) -> T
130 where
131 T: ToFieldElements<F>,
132 {
133 data
134 }
135}
136
137impl<L: LedgerNonSnark> ZkappHandler for NonSnarkHandler<L> {
138 type Z = ZkappNonSnark<L>;
139 type AccountUpdate = AccountUpdate;
140 type Account = Account;
141 type Bool = bool;
142 type W = ();
143 type GlobalState = GlobalStateForNonSnark<L>;
144
145 fn check_account_precondition(
146 account_update: &Self::AccountUpdate,
147 account: &Self::Account,
148 new_account: Self::Bool,
149 local_state: &mut zkapp_logic::LocalState<ZkappNonSnark<L>>,
150 w: &mut Self::W,
151 ) {
152 let precondition_account = &account_update.body.preconditions.account;
153 let check = |failure, b: Boolean, _: &mut Witness<Fp>| {
154 zkapp_logic::LocalState::<ZkappNonSnark<L>>::add_check(
155 local_state,
156 failure,
157 b.as_bool(),
158 w,
159 );
160 };
161 let mut w = Witness::empty();
162 precondition_account.zcheck::<NonSnarkOps, _>(
163 new_account.to_boolean(),
164 account,
165 check,
166 &mut w,
167 );
168 }
169
170 fn check_protocol_state_precondition(
171 protocol_state_predicate: &zkapp_command::ZkAppPreconditions,
172 global_state: &mut Self::GlobalState,
173 w: &mut Self::W,
174 ) -> Self::Bool {
175 let mut w = Witness::empty();
176 protocol_state_predicate
177 .zcheck::<NonSnarkOps>(&global_state.protocol_state, &mut w)
178 .as_bool()
179 }
180
181 fn check_valid_while_precondition(
182 valid_while: &zkapp_command::Numeric<crate::scan_state::currency::Slot>,
183 global_state: &mut Self::GlobalState,
184 w: &mut Self::W,
185 ) -> Self::Bool {
186 use zkapp_command::ClosedInterval;
187 let mut w = Witness::empty();
188 (valid_while, ClosedInterval::min_max)
189 .zcheck::<NonSnarkOps>(&global_state.block_global_slot, &mut w)
190 .as_bool()
191 }
192
193 fn init_account(
194 _account_update: &Self::AccountUpdate,
195 account: Self::Account,
196 ) -> Self::Account {
197 account
198 }
199}
200
201impl ReceiptChainHashInterface for NonSnarkReceiptChainHash {
202 type W = ();
203 type Index = Index;
204
205 fn cons_zkapp_command_commitment(
206 index: Self::Index,
207 element: Fp,
208 other: crate::ReceiptChainHash,
209 w: &mut Self::W,
210 ) -> crate::ReceiptChainHash {
211 use crate::scan_state::transaction_logic::cons_zkapp_command_commitment;
212
213 cons_zkapp_command_commitment(
214 index,
215 ZkAppCommandElt::ZkAppCommandCommitment(crate::ReceiptChainHash(element)),
216 &other,
217 )
218 }
219}
220
221impl ActionsInterface for NonSnarkActions {
222 type W = ();
223 type Bool = bool;
224
225 fn is_empty(
226 actions: &crate::scan_state::transaction_logic::zkapp_command::Actions,
227 _w: &mut Self::W,
228 ) -> Self::Bool {
229 actions.is_empty()
230 }
231
232 fn push_events(
233 event: Fp,
234 actions: &crate::scan_state::transaction_logic::zkapp_command::Actions,
235 _w: &mut Self::W,
236 ) -> Fp {
237 actions.push_events(event)
238 }
239}
240
241impl SetOrKeepInterface for NonSnarkSetOrKeep {
242 type Bool = bool;
243
244 fn is_keep<T: Clone>(set_or_keep: &SetOrKeep<T>) -> Self::Bool {
245 set_or_keep.is_keep()
246 }
247
248 fn is_set<T: Clone>(set_or_keep: &SetOrKeep<T>) -> Self::Bool {
249 set_or_keep.is_set()
250 }
251}
252
253impl GlobalSlotSpanInterface for NonSnarkGlobalSlotSpan {
254 type W = ();
255 type Bool = bool;
256 type SlotSpan = SlotSpan;
257
258 fn greater_than(this: &Self::SlotSpan, other: &Self::SlotSpan, w: &mut Self::W) -> Self::Bool {
259 this > other
260 }
261}
262
263impl TxnVersionInterface for TxnVersion {
264 type W = ();
265 type Bool = bool;
266
267 fn equal_to_current(version: TxnVersion, w: &mut Self::W) -> Self::Bool {
268 version == TXN_VERSION_CURRENT
269 }
270
271 fn older_than_current(version: TxnVersion, w: &mut Self::W) -> Self::Bool {
272 version < TXN_VERSION_CURRENT
273 }
274}
275
276impl VerificationKeyHashInterface for NonSnarkVerificationKeyHash {
277 type W = ();
278 type Bool = bool;
279
280 fn equal(a: &Self, b: &Self, _w: &mut Self::W) -> Self::Bool {
281 a == b
282 }
283}
284
285impl TransactionCommitmentInterface for TransactionCommitment {
286 type AccountUpdate = AccountUpdate;
287 type CallForest = CallForest<AccountUpdate>;
288 type W = ();
289
290 fn empty() -> Fp {
291 let TransactionCommitment(fp) = TransactionCommitment::empty();
292 fp
293 }
294 fn commitment(account_updates: &Self::CallForest) -> Fp {
295 let account_updates_hash = account_updates.hash();
296 let TransactionCommitment(fp) = TransactionCommitment::create(account_updates_hash);
297 fp
298 }
299 fn full_commitment(
300 account_update: &Self::AccountUpdate,
301 memo_hash: Fp,
302 commitment: Fp,
303 w: &mut Self::W,
304 ) -> Fp {
305 let fee_payer_hash = account_update.digest();
307 let TransactionCommitment(fp) =
308 TransactionCommitment(commitment).create_complete(memo_hash, fee_payer_hash);
309 fp
310 }
311}
312
313impl AccountIdInterface for AccountId {
314 type W = ();
315
316 fn derive_token_id(account_id: &AccountId, w: &mut Self::W) -> TokenId {
317 account_id.derive_token_id()
318 }
319}
320
321impl TokenIdInterface for TokenId {
322 type W = ();
323 type Bool = bool;
324
325 fn equal(a: &TokenId, b: &TokenId, w: &mut Self::W) -> Self::Bool {
326 a == b
327 }
328}
329
330impl<L: LedgerNonSnark> LocalStateInterface for zkapp_logic::LocalState<ZkappNonSnark<L>> {
331 type Z = ZkappNonSnark<L>;
332 type Bool = bool;
333 type W = ();
334
335 fn add_check(
336 local: &mut zkapp_logic::LocalState<Self::Z>,
337 failure: TransactionFailure,
338 b: Self::Bool,
339 w: &mut Self::W,
340 ) {
341 if !b {
342 local.failure_status_tbl[0].insert(0, failure);
343 }
344 local.success = local.success && b;
345 }
346
347 fn add_new_failure_status_bucket(local: &mut zkapp_logic::LocalState<Self::Z>) {
348 local.failure_status_tbl.insert(0, Vec::new());
349 }
350}
351
352impl AmountInterface for Amount {
353 type W = ();
354 type Bool = bool;
355 fn zero() -> Self {
356 <Amount as Magnitude>::zero()
357 }
358 fn of_constant_fee(fee: crate::scan_state::currency::Fee) -> Self {
359 Amount::of_fee(&fee)
360 }
361}
362
363impl BalanceInterface for Balance {
364 type W = ();
365 type Bool = bool;
366 type Amount = Amount;
367 type SignedAmount = Signed<Amount>;
368
369 fn add_signed_amount_flagged(
370 &self,
371 signed_amount: Self::SignedAmount,
372 _w: &mut Self::W,
373 ) -> (Self, Self::Bool) {
374 self.add_signed_amount_flagged(signed_amount)
375 }
376}
377
378impl SignedAmountInterface for Signed<Amount> {
379 type W = ();
380 type Bool = bool;
381 type Amount = Amount;
382
383 fn zero() -> Self {
384 Self::zero()
385 }
386 fn is_neg(&self) -> Self::Bool {
387 self.is_neg()
388 }
389 fn equal(&self, other: &Self, _w: &mut Self::W) -> Self::Bool {
390 (self == other)
391 }
392 fn is_non_neg(&self) -> Self::Bool {
393 self.is_non_neg()
394 }
395 fn negate(&self) -> Self {
396 self.negate()
397 }
398 fn add_flagged(&self, other: &Self, _w: &mut Self::W) -> (Self, Self::Bool) {
399 self.add_flagged(*other)
400 }
401 fn of_unsigned(unsigned: Self::Amount) -> Self {
402 Self::of_unsigned(unsigned)
403 }
404 fn on_if(b: Self::Bool, param: SignedAmountBranchParam<&Self>, w: &mut Self::W) -> Self {
405 let SignedAmountBranchParam { on_true, on_false } = param;
406 match b {
407 true => *on_true,
408 false => *on_false,
409 }
410 }
411}
412
413impl GlobalSlotSinceGenesisInterface for Slot {
414 type W = ();
415 type Bool = bool;
416
417 fn equal(&self, other: &Self, w: &mut Self::W) -> Self::Bool {
418 self == other
419 }
420
421 fn exists_no_check(self, w: &mut Self::W) -> Self {
422 self
423 }
424}
425
426impl<L: LedgerIntf + Clone> GlobalStateInterface for GlobalStateForNonSnark<L> {
427 type Ledger = L;
428 type W = ();
429 type Bool = bool;
430 type SignedAmount = Signed<Amount>;
431 type GlobalSlotSinceGenesis = Slot;
432
433 fn first_pass_ledger(&self) -> Self::Ledger {
434 self.first_pass_ledger.create_masked()
435 }
436 fn set_first_pass_ledger(
437 &mut self,
438 should_update: Self::Bool,
439 ledger: &Self::Ledger,
440 _w: &mut Self::W,
441 ) {
442 if should_update {
443 self.first_pass_ledger.apply_mask(ledger.clone());
444 }
445 }
446 fn second_pass_ledger(&self) -> Self::Ledger {
447 self.second_pass_ledger.create_masked()
448 }
449 fn set_second_pass_ledger(
450 &mut self,
451 should_update: Self::Bool,
452 ledger: &Self::Ledger,
453 _w: &mut Self::W,
454 ) {
455 if should_update {
456 self.second_pass_ledger.apply_mask(ledger.clone());
457 }
458 }
459 fn fee_excess(&self) -> Self::SignedAmount {
460 self.fee_excess
461 }
462 fn set_fee_excess(&mut self, fee_excess: Self::SignedAmount) {
463 self.fee_excess = fee_excess;
464 }
465 fn supply_increase(&self) -> Self::SignedAmount {
466 self.supply_increase
467 }
468 fn set_supply_increase(&mut self, supply_increase: Self::SignedAmount) {
469 self.supply_increase = supply_increase;
470 }
471 fn block_global_slot(&self) -> Self::GlobalSlotSinceGenesis {
472 self.block_global_slot
473 }
474}
475
476impl StackFrameInterface for StackFrame {
477 type Calls = CallForest<AccountUpdate>;
478 type W = ();
479 type Bool = bool;
480
481 fn caller(&self) -> crate::TokenId {
482 let Self {
483 caller,
484 caller_caller: _,
485 calls: _,
486 } = self;
487 caller.clone()
488 }
489 fn caller_caller(&self) -> crate::TokenId {
490 let Self {
491 caller: _,
492 caller_caller,
493 calls: _,
494 } = self;
495 caller_caller.clone()
496 }
497 fn calls(&self) -> &CallForest<AccountUpdate> {
498 let Self {
499 caller: _,
500 caller_caller: _,
501 calls,
502 } = self;
503 calls
504 }
505 fn make(params: StackFrameMakeParams<'_, Self::Calls>) -> Self {
506 let StackFrameMakeParams {
507 caller,
508 caller_caller,
509 calls,
510 } = params;
511 Self {
512 caller,
513 caller_caller,
514 calls: calls.clone(),
515 }
516 }
517 fn make_default(params: StackFrameMakeParams<'_, Self::Calls>) -> Self {
518 Self::make(params) }
520 fn on_if<F: FnOnce(&mut Self::W) -> Self, F2: FnOnce(&mut Self::W) -> Self>(
521 b: Self::Bool,
522 param: BranchParam<Self, Self::W, F, F2>,
523 w: &mut Self::W,
524 ) -> Self {
525 let BranchParam { on_true, on_false } = param;
526
527 match b {
528 true => on_true.eval(w),
529 false => on_false.eval(w),
530 }
531 }
532}
533
534impl<F: FieldWitness> ToFieldElements<F> for CallStack {
535 fn to_field_elements(&self, fields: &mut Vec<F>) {
536 unreachable!()
537 }
538}
539
540impl StackInterface for CallStack {
541 type Elt = StackFrame;
542 type W = ();
543 type Bool = bool;
544
545 fn empty() -> Self {
546 Self::default()
547 }
548 fn is_empty(&self, _w: &mut Self::W) -> Self::Bool {
549 self.is_empty()
550 }
551 fn pop(&self, _w: &mut Self::W) -> Opt<(Self::Elt, Self)> {
552 Opt::from_option(self.pop())
553 }
554 fn push(elt: Self::Elt, onto: Self, _w: &mut Self::W) -> Self {
555 onto.push(&elt)
556 }
557}
558
559impl CallStackInterface for CallStack {
560 type StackFrame = StackFrame;
561}
562
563impl IndexInterface for Index {
564 fn zero() -> Self {
565 <Index as Magnitude>::zero()
566 }
567 fn succ(&self) -> Self {
568 self.incr()
569 }
570}
571
572impl CallForestInterface for CallForest<AccountUpdate> {
573 type W = ();
574 type AccountUpdate = AccountUpdate;
575 type Bool = bool;
576
577 fn empty() -> Self {
578 Self::empty()
579 }
580 fn is_empty(&self, _w: &mut Self::W) -> Self::Bool {
581 self.is_empty()
582 }
583 fn pop_exn(&self, _w: &mut Self::W) -> ((AccountUpdate, Self), Self) {
584 self.pop_exn()
585 }
586}
587
588impl BoolInterface for bool {
589 type W = ();
590 type FailureStatusTable = Vec<Vec<TransactionFailure>>;
591
592 fn as_boolean(&self) -> Boolean {
593 self.to_boolean()
594 }
595 fn of_boolean(b: Boolean) -> Self {
596 b.as_bool()
597 }
598 fn true_() -> Self {
599 true
600 }
601 fn false_() -> Self {
602 false
603 }
604 fn neg(&self) -> Self {
605 !self
606 }
607 fn or(a: Self, b: Self, w: &mut Self::W) -> Self {
608 a || b
609 }
610 fn and(a: Self, b: Self, w: &mut Self::W) -> Self {
611 a && b
612 }
613 fn equal(a: Self, b: Self, w: &mut Self::W) -> Self {
614 a == b
615 }
616 fn all(bs: &[Self], w: &mut Self::W) -> Self {
617 bs.iter().all(|b| *b)
618 }
619 fn assert_any(bs: &[Self], w: &mut Self::W) -> Result<(), String> {
620 if !bs.iter().any(|b| *b) {
621 return Err("Bool::assert_any failed".to_string());
622 }
623 Ok(())
624 }
625 fn assert_with_failure_status_tbl(
626 b: Self,
627 failure_status_tbl: &Self::FailureStatusTable,
628 ) -> Result<(), String> {
629 if !b && !(failure_status_tbl.is_empty()) {
630 Err(format!("{:?}", failure_status_tbl))
631 } else if !b {
632 Err("assert_with_failure_status_tbl failed".to_string())
633 } else {
634 Ok(())
635 }
636 }
637}
638
639impl AccountInterface for Account {
640 type W = ();
641 type Bool = bool;
642 type Balance = Balance;
643 type GlobalSlot = Slot;
644 type D = ();
645 type VerificationKeyHash = NonSnarkVerificationKeyHash;
646
647 fn register_verification_key(&self, data: &Self::D, w: &mut Self::W) {
648 }
650
651 fn get(&self) -> &Account {
652 self
653 }
654
655 fn get_mut(&mut self) -> &mut Account {
656 self
657 }
658
659 fn set_delegate(&mut self, new: CompressedPubKey) {
660 self.delegate = if new == CompressedPubKey::empty() {
661 None
662 } else {
663 Some(new)
664 };
665 }
666
667 fn zkapp(&self) -> MyCow<'_, ZkAppAccount> {
668 match self.zkapp.as_ref() {
669 Some(zkapp) => MyCow::Borrow(zkapp),
670 None => MyCow::Own(ZkAppAccount::default()),
671 }
672 }
673
674 fn zkapp_mut(&mut self) -> &mut ZkAppAccount {
675 self.zkapp.as_mut().unwrap()
677 }
678
679 fn verification_key_hash(&self) -> NonSnarkVerificationKeyHash {
680 Some(self.zkapp.as_ref()?.verification_key.as_ref()?.hash())
681 }
682
683 fn set_token_id(&mut self, token_id: TokenId) {
684 self.token_id = token_id;
685 }
686
687 fn is_timed(&self) -> Self::Bool {
688 match &self.timing {
689 crate::Timing::Untimed => false,
690 crate::Timing::Timed { .. } => true,
691 }
692 }
693
694 fn balance(&self) -> Self::Balance {
695 self.balance
696 }
697
698 fn set_balance(&mut self, balance: Self::Balance) {
699 self.balance = balance;
700 }
701
702 fn check_timing(
703 &self,
704 txn_global_slot: &Self::GlobalSlot,
705 w: &mut Self::W,
706 ) -> (TimingValidation<Self::Bool>, crate::Timing) {
707 account_check_timing(txn_global_slot, self)
708 }
709
710 fn make_zkapp(&mut self) {
711 if self.zkapp.is_none() {
712 self.zkapp = Some(Box::default());
714 }
715 }
716
717 fn unmake_zkapp(&mut self) {
718 if self.zkapp.as_ref().map(|z| z.is_default()).unwrap_or(false) {
719 self.zkapp = None;
720 }
721 }
722
723 fn proved_state(&self) -> Self::Bool {
724 self.zkapp().proved_state
725 }
726
727 fn set_proved_state(&mut self, proved_state: Self::Bool) {
728 self.zkapp_mut().proved_state = proved_state;
729 }
730
731 fn app_state(&self) -> [Fp; 8] {
732 self.zkapp().app_state
733 }
734
735 fn last_action_slot(&self) -> Self::GlobalSlot {
736 self.zkapp().last_action_slot
737 }
738
739 fn set_last_action_slot(&mut self, slot: Self::GlobalSlot) {
740 self.zkapp_mut().last_action_slot = slot;
741 }
742}
743
744impl AccountUpdateInterface for AccountUpdate {
745 type W = ();
746 type SingleData = ();
747 type CallForest = CallForest<AccountUpdate>;
748 type Bool = bool;
749 type SignedAmount = Signed<Amount>;
750 type VerificationKeyHash = NonSnarkVerificationKeyHash;
751
752 fn body(&self) -> &crate::scan_state::transaction_logic::zkapp_command::Body {
753 let Self {
754 body,
755 authorization: _,
756 } = self;
757 body
758 }
759 fn is_proved(&self) -> Self::Bool {
760 self.body().authorization_kind.is_proved()
761 }
762 fn is_signed(&self) -> Self::Bool {
763 self.body().authorization_kind.is_signed()
764 }
765 fn verification_key_hash(&self) -> Self::VerificationKeyHash {
766 use crate::scan_state::transaction_logic::zkapp_command::AuthorizationKind::*;
767
768 match &self.body().authorization_kind {
769 Proof(vk_hash) => Some(*vk_hash),
770 NoneGiven | Signature => None,
771 }
772 }
773 fn check_authorization(
774 &self,
775 will_succeed: Self::Bool,
776 commitment: Fp,
777 calls: &Self::CallForest,
778 single_data: &Self::SingleData,
779 w: &mut Self::W,
780 ) -> CheckAuthorizationResult<Self::Bool> {
781 use crate::scan_state::transaction_logic::zkapp_command::Control::*;
782
783 let (proof_verifies, signature_verifies) = match &self.authorization {
784 Signature(_) => (false, true),
785 Proof(_) => (true, false),
786 NoneGiven => (false, false),
787 };
788 CheckAuthorizationResult {
789 proof_verifies,
790 signature_verifies,
791 }
792 }
793 fn increment_nonce(&self) -> Self::Bool {
794 self.body().increment_nonce
795 }
796 fn use_full_commitment(&self) -> Self::Bool {
797 self.body().use_full_commitment
798 }
799 fn account_precondition_nonce_is_constant(&self, w: &mut Self::W) -> Self::Bool {
800 let nonce = self.body().preconditions.account.nonce();
801 nonce.is_constant()
802 }
803 fn implicit_account_creation_fee(&self) -> Self::Bool {
804 self.body().implicit_account_creation_fee
805 }
806 fn balance_change(&self) -> Self::SignedAmount {
807 self.body().balance_change
808 }
809}
810
811fn controller_check(
812 proof_verifies: bool,
813 signature_verifies: bool,
814 perm: AuthRequired,
815) -> Result<bool, String> {
816 if proof_verifies && signature_verifies {
818 return Err("We either have a proof, a signature, or neither.".to_string());
819 }
820 let tag = if proof_verifies {
821 ControlTag::Proof
822 } else if signature_verifies {
823 ControlTag::Signature
824 } else {
825 ControlTag::NoneGiven
826 };
827 Ok(check_permission(perm, tag))
828}
829
830impl ControllerInterface for NonSnarkController {
831 type W = ();
832 type Bool = bool;
833 type SingleData = ();
834
835 fn check(
836 proof_verifies: Self::Bool,
837 signature_verifies: Self::Bool,
838 auth: &AuthRequired,
839 _single_data: &Self::SingleData,
840 _w: &mut Self::W,
841 ) -> Result<Self::Bool, String> {
842 controller_check(proof_verifies, signature_verifies, *auth)
843 }
844
845 fn verification_key_perm_fallback_to_signature_with_older_version(
846 auth: &AuthRequired,
847 w: &mut Self::W,
848 ) -> AuthRequired {
849 auth.verification_key_perm_fallback_to_signature_with_older_version()
850 }
851}
852
853pub struct NonSnarkBranch;
854
855impl BranchInterface for NonSnarkBranch {
856 type W = ();
857
858 fn make<T, F>(_w: &mut Self::W, run: F) -> BranchEvaluation<T, Self::W, F>
859 where
860 F: FnOnce(&mut Self::W) -> T,
861 {
862 BranchEvaluation::Pending(run)
865 }
866}
867
868fn get_with_location<L>(
869 ledger: &L,
870 account_id: &AccountId,
871) -> Result<(ExistingOrNew<L::Location>, Box<Account>), String>
872where
873 L: LedgerIntf,
874{
875 match ledger.location_of_account(account_id) {
876 Some(location) => match ledger.get(&location) {
877 Some(account) => Ok((ExistingOrNew::Existing(location), account)),
878 None => Err("Ledger location with no account".to_string()),
879 },
880 None => Ok((
881 ExistingOrNew::New,
882 Box::new(Account::create_with(account_id.clone(), Balance::zero())),
883 )),
884 }
885}
886
887mod ledger {
888 use super::*;
889
890 type InclusionProof<L> = ExistingOrNew<<L as LedgerIntf>::Location>;
891
892 pub(super) fn get_account<L: LedgerIntf>(
893 ledger: &L,
894 account_update: &AccountUpdate,
895 ) -> Result<(Account, InclusionProof<L>), String> {
896 let (loc, account) = get_with_location(ledger, &account_update.account_id())?;
897 Ok((*account, loc))
898 }
899 pub(super) fn set_account<L: LedgerIntf>(
900 ledger: &mut L,
901 account: (Account, InclusionProof<L>),
902 ) -> Result<(), String> {
903 let (account, location) = account;
904 set_with_location(ledger, &location, Box::new(account))
905 }
906 pub(super) fn check_account<L: LedgerIntf>(
907 public_key: &CompressedPubKey,
908 token_id: &TokenId,
909 account: (&Account, &InclusionProof<L>),
910 ) -> Result<bool, String> {
911 let (account, loc) = account;
912 if public_key != &account.public_key {
913 return Err("check_account: public_key != &account.public_key".to_string());
914 }
915 if token_id != &account.token_id {
916 return Err("check_account: token_id != &account.token_id".to_string());
917 }
918 match loc {
919 ExistingOrNew::Existing(_) => Ok(false),
920 ExistingOrNew::New => Ok(true),
921 }
922 }
923}
924
925impl LedgerInterface for Mask {
926 type W = ();
927 type AccountUpdate = AccountUpdate;
928 type Account = Account;
929 type Bool = bool;
930 type InclusionProof = ExistingOrNew<<Mask as LedgerIntf>::Location>;
931
932 fn empty(depth: usize) -> Self {
933 <Self as LedgerIntf>::empty(depth)
934 }
935 fn get_account(
936 &self,
937 account_update: &Self::AccountUpdate,
938 _w: &mut Self::W,
939 ) -> Result<(Self::Account, Self::InclusionProof), String> {
940 ledger::get_account(self, account_update)
941 }
942 fn set_account(
943 &mut self,
944 account: (Self::Account, Self::InclusionProof),
945 _w: &mut Self::W,
946 ) -> Result<(), String> {
947 ledger::set_account(self, account)
948 }
949 fn check_inclusion(&self, _account: &(Self::Account, Self::InclusionProof), _w: &mut Self::W) {
950 }
952 fn check_account(
953 public_key: &CompressedPubKey,
954 token_id: &TokenId,
955 account: (&Self::Account, &Self::InclusionProof),
956 _w: &mut Self::W,
957 ) -> Result<Self::Bool, String> {
958 ledger::check_account::<Self>(public_key, token_id, account)
959 }
960}
961impl LedgerInterface for SparseLedger {
962 type W = ();
963 type AccountUpdate = AccountUpdate;
964 type Account = Account;
965 type Bool = bool;
966 type InclusionProof = ExistingOrNew<<Mask as LedgerIntf>::Location>;
967
968 fn empty(depth: usize) -> Self {
969 <Self as LedgerIntf>::empty(depth)
970 }
971 fn get_account(
972 &self,
973 account_update: &Self::AccountUpdate,
974 _w: &mut Self::W,
975 ) -> Result<(Self::Account, Self::InclusionProof), String> {
976 ledger::get_account(self, account_update)
977 }
978 fn set_account(
979 &mut self,
980 account: (Self::Account, Self::InclusionProof),
981 _w: &mut Self::W,
982 ) -> Result<(), String> {
983 ledger::set_account(self, account)
984 }
985 fn check_inclusion(&self, _account: &(Self::Account, Self::InclusionProof), _w: &mut Self::W) {
986 }
988 fn check_account(
989 public_key: &CompressedPubKey,
990 token_id: &TokenId,
991 account: (&Self::Account, &Self::InclusionProof),
992 _w: &mut Self::W,
993 ) -> Result<Self::Bool, String> {
994 ledger::check_account::<Self>(public_key, token_id, account)
995 }
996}
997
998pub fn step<L>(
999 global_state: &mut GlobalStateForNonSnark<L>,
1000 local_state: &mut zkapp_logic::LocalState<ZkappNonSnark<L>>,
1001) -> Result<(), String>
1002where
1003 L: LedgerNonSnark,
1004{
1005 zkapp_logic::apply(
1006 ApplyZkappParams {
1007 is_start: zkapp_logic::IsStart::No,
1008 global_state,
1009 local_state,
1010 single_data: (),
1011 },
1012 &mut (),
1013 )
1014}
1015
1016pub type StartData = StartDataSkeleton<CallForest<AccountUpdate>, bool>;
1017
1018pub fn start<L>(
1019 global_state: &mut GlobalStateForNonSnark<L>,
1020 local_state: &mut zkapp_logic::LocalState<ZkappNonSnark<L>>,
1021 start_data: StartData,
1022) -> Result<(), String>
1023where
1024 L: LedgerNonSnark,
1025{
1026 zkapp_logic::apply(
1027 ApplyZkappParams {
1028 is_start: zkapp_logic::IsStart::Yes(start_data),
1029 global_state,
1030 local_state,
1031 single_data: (),
1032 },
1033 &mut (),
1034 )
1035}