From 08eb0228a311bf94b41ebbaf8829f63dd39411e3 Mon Sep 17 00:00:00 2001 From: glyh Date: Wed, 3 Dec 2025 18:04:11 +0800 Subject: [PATCH 1/2] zkapp account update: implement permission fallback for access --- src/lib/mina_base/permissions.ml | 16 +++++++++ src/lib/mina_base/permissions.mli | 4 +++ .../mina_transaction_logic.ml | 4 +++ .../transaction_logic/zkapp_command_logic.ml | 34 ++++++++++--------- .../transaction_snark/transaction_snark.ml | 4 +++ 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/lib/mina_base/permissions.ml b/src/lib/mina_base/permissions.ml index 43ef84cb02ee..155ab1186ddb 100644 --- a/src/lib/mina_base/permissions.ml +++ b/src/lib/mina_base/permissions.ml @@ -72,6 +72,12 @@ module Auth_required = struct | t -> t + let access_perm_fallback_to_signature_with_older_version = function + | Proof -> + Signature + | t -> + t + (* permissions such that [check permission (Proof _)] is true *) let gen_for_proof_authorization : t Quickcheck.Generator.t = Quickcheck.Generator.of_list [ None; Either; Proof ] @@ -294,11 +300,21 @@ module Auth_required = struct that the proof should verify. *) (result, `proof_must_verify (didn't_fail_yet &&& not signature_sufficient)) + (* proof/either/impossible -> signature *) let verification_key_perm_fallback_to_signature_with_older_version ({ signature_sufficient; _ } as t : t) = if_ Pickles.Impls.Step.Boolean.(not signature_sufficient) ~then_:(constant Signature) ~else_:t + + (* proof/either -> signature *) + let access_perm_fallback_to_signature_with_older_version + ({ signature_sufficient; constant = signature_is_constant; _ } as t : t) + = + if_ + Pickles.Impls.Step.Boolean.( + (not signature_sufficient) && not signature_is_constant) + ~then_:(constant Signature) ~else_:t end let typ = diff --git a/src/lib/mina_base/permissions.mli b/src/lib/mina_base/permissions.mli index e74ccfd18abe..2e0ecfbc5335 100644 --- a/src/lib/mina_base/permissions.mli +++ b/src/lib/mina_base/permissions.mli @@ -27,6 +27,8 @@ module Auth_required : sig val verification_key_perm_fallback_to_signature_with_older_version : t -> t + val access_perm_fallback_to_signature_with_older_version : t -> t + module Checked : sig type t @@ -44,6 +46,8 @@ module Auth_required : sig -> Boolean.var * [ `proof_must_verify of Boolean.var ] val verification_key_perm_fallback_to_signature_with_older_version : t -> t + + val access_perm_fallback_to_signature_with_older_version : t -> t end val typ : (Checked.t, t) Typ.t diff --git a/src/lib/transaction_logic/mina_transaction_logic.ml b/src/lib/transaction_logic/mina_transaction_logic.ml index f6b5f0617ced..57c0bb1e8e7d 100644 --- a/src/lib/transaction_logic/mina_transaction_logic.ml +++ b/src/lib/transaction_logic/mina_transaction_logic.ml @@ -1006,6 +1006,10 @@ module Make (L : Ledger_intf.S) : let verification_key_perm_fallback_to_signature_with_older_version = Permissions.Auth_required .verification_key_perm_fallback_to_signature_with_older_version + + let access_perm_fallback_to_signature_with_older_version = + Permissions.Auth_required + .access_perm_fallback_to_signature_with_older_version end module Txn_version = struct diff --git a/src/lib/transaction_logic/zkapp_command_logic.ml b/src/lib/transaction_logic/zkapp_command_logic.ml index 0b24f9c9f8a6..f6e4908ef494 100644 --- a/src/lib/transaction_logic/zkapp_command_logic.ml +++ b/src/lib/transaction_logic/zkapp_command_logic.ml @@ -550,6 +550,8 @@ module type Controller_intf = sig val check : proof_verifies:bool -> signature_verifies:bool -> t -> bool val verification_key_perm_fallback_to_signature_with_older_version : t -> t + + val access_perm_fallback_to_signature_with_older_version : t -> t end module type Txn_version_intf = sig @@ -1546,11 +1548,19 @@ module Make (Inputs : Inputs_intf) = struct This must be done before updating zkApp fields! *) let a = Account.make_zkapp a in + let auth_with_fallback ~fallback_logic auth = + Account.Permissions.set_verification_key_txn_version a + |> Txn_version.older_than_current + |> Controller.if_ ~then_:(fallback_logic auth) ~else_:auth + in (* Check that the account can be accessed with the given authorization. *) let local_state = let has_permission = - Controller.check ~proof_verifies ~signature_verifies - (Account.Permissions.access a) + Account.Permissions.access a + |> auth_with_fallback + ~fallback_logic: + Controller.access_perm_fallback_to_signature_with_older_version + |> Controller.check ~proof_verifies ~signature_verifies in Local_state.add_check local_state Update_not_permitted_access has_permission @@ -1614,21 +1624,13 @@ module Make (Inputs : Inputs_intf) = struct let verification_key = Account_update.Update.verification_key account_update in - let older_than_current_version = - Txn_version.older_than_current - (Account.Permissions.set_verification_key_txn_version a) - in - let original_auth = Account.Permissions.set_verification_key_auth a in - let auth = - Controller.if_ older_than_current_version - ~then_: - (Controller - .verification_key_perm_fallback_to_signature_with_older_version - original_auth ) - ~else_:original_auth - in let has_permission = - Controller.check ~proof_verifies ~signature_verifies auth + Account.Permissions.set_verification_key_auth a + |> auth_with_fallback + ~fallback_logic: + Controller + .verification_key_perm_fallback_to_signature_with_older_version + |> Controller.check ~proof_verifies ~signature_verifies in let local_state = Local_state.add_check local_state Update_not_permitted_verification_key diff --git a/src/lib/transaction_snark/transaction_snark.ml b/src/lib/transaction_snark/transaction_snark.ml index 7ee65f8663db..9541b896e94a 100644 --- a/src/lib/transaction_snark/transaction_snark.ml +++ b/src/lib/transaction_snark/transaction_snark.ml @@ -1473,6 +1473,10 @@ module Make_str (A : Wire_types.Concrete) = struct let verification_key_perm_fallback_to_signature_with_older_version = Permissions.Auth_required.Checked .verification_key_perm_fallback_to_signature_with_older_version + + let access_perm_fallback_to_signature_with_older_version = + Permissions.Auth_required.Checked + .access_perm_fallback_to_signature_with_older_version end module Txn_version = struct From 3793c4cfbeb6d5c5b1e034b5fc973818a20aff5b Mon Sep 17 00:00:00 2001 From: glyh Date: Wed, 3 Dec 2025 22:50:48 +0800 Subject: [PATCH 2/2] zkapp account update: auto bump txn version to current on setting verification key --- .../mina_transaction_logic.ml | 25 +++++++++++++--- .../transaction_logic/zkapp_command_logic.ml | 22 +++++++------- .../transaction_snark/transaction_snark.ml | 30 ++++++++++++++----- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/lib/transaction_logic/mina_transaction_logic.ml b/src/lib/transaction_logic/mina_transaction_logic.ml index 57c0bb1e8e7d..57105815771b 100644 --- a/src/lib/transaction_logic/mina_transaction_logic.ml +++ b/src/lib/transaction_logic/mina_transaction_logic.ml @@ -1136,9 +1136,6 @@ module Make (L : Ledger_intf.S) : let set_verification_key_auth : t -> Controller.t = fun a -> fst a.permissions.set_verification_key - let set_verification_key_txn_version : t -> Txn_version.t = - fun a -> snd a.permissions.set_verification_key - let set_zkapp_uri : t -> Controller.t = fun a -> a.permissions.set_zkapp_uri @@ -1288,9 +1285,29 @@ module Make (L : Ledger_intf.S) : let set_voting_for voting_for (a : t) = { a with voting_for } + type txn_version = Txn_version.t + + let txn_version (a : t) : txn_version = + snd a.permissions.set_verification_key + let permissions (a : t) = a.permissions - let set_permissions permissions (a : t) = { a with permissions } + let set_permissions_ignore_vk_txn_version (permissions : Permissions.t) + (a : t) = + let vk_txn_version = txn_version a in + let set_verification_key = + (fst permissions.set_verification_key, vk_txn_version) + in + let permissions = { permissions with set_verification_key } in + { a with permissions } + + let set_txn_version_to_current (a : t) = + let set_verification_key = + ( fst a.permissions.set_verification_key + , Mina_numbers.Txn_version.current ) + in + let permissions = { a.permissions with set_verification_key } in + { a with permissions } end module Amount = struct diff --git a/src/lib/transaction_logic/zkapp_command_logic.ml b/src/lib/transaction_logic/zkapp_command_logic.ml index f6e4908ef494..f800b5f8f217 100644 --- a/src/lib/transaction_logic/zkapp_command_logic.ml +++ b/src/lib/transaction_logic/zkapp_command_logic.ml @@ -574,8 +574,6 @@ module type Account_intf = sig module Permissions : sig type controller - type txn_version - val access : t -> controller val edit_state : t -> controller @@ -590,8 +588,6 @@ module type Account_intf = sig val set_verification_key_auth : t -> controller - val set_verification_key_txn_version : t -> txn_version - val set_zkapp_uri : t -> controller val edit_action_state : t -> controller @@ -710,7 +706,13 @@ module type Account_intf = sig val permissions : t -> Permissions.t - val set_permissions : Permissions.t -> t -> t + val set_permissions_ignore_vk_txn_version : Permissions.t -> t -> t + + type txn_version + + val txn_version : t -> txn_version + + val set_txn_version_to_current : t -> t end module Eff = struct @@ -825,7 +827,6 @@ module type Inputs_intf = sig and Account : (Account_intf with type Permissions.controller := Controller.t - and type Permissions.txn_version := Txn_version.t and type timing := Timing.t and type balance := Balance.t and type receipt_chain_hash := Receipt_chain_hash.t @@ -840,7 +841,8 @@ module type Inputs_intf = sig and type nonce := Nonce.t and type state_hash := State_hash.t and type token_id := Token_id.t - and type account_id := Account_id.t) + and type account_id := Account_id.t + and type txn_version = Txn_version.t) and Actions : (Actions_intf with type bool := Bool.t and type field := Field.t) @@ -1549,8 +1551,7 @@ module Make (Inputs : Inputs_intf) = struct *) let a = Account.make_zkapp a in let auth_with_fallback ~fallback_logic auth = - Account.Permissions.set_verification_key_txn_version a - |> Txn_version.older_than_current + Account.txn_version a |> Txn_version.older_than_current |> Controller.if_ ~then_:(fallback_logic auth) ~else_:auth in (* Check that the account can be accessed with the given authorization. *) @@ -1641,6 +1642,7 @@ module Make (Inputs : Inputs_intf) = struct (Account.verification_key a) in let a = Account.set_verification_key verification_key a in + let a = Account.set_txn_version_to_current a in (a, local_state) in (* Update action state. *) @@ -1808,7 +1810,7 @@ module Make (Inputs : Inputs_intf) = struct Set_or_keep.set_or_keep ~if_:Account.Permissions.if_ permissions (Account.permissions a) in - let a = Account.set_permissions permissions a in + let a = Account.set_permissions_ignore_vk_txn_version permissions a in (a, local_state) in (* Initialize account's pk, in case it is new. *) diff --git a/src/lib/transaction_snark/transaction_snark.ml b/src/lib/transaction_snark/transaction_snark.ml index 9541b896e94a..4d8ff3414e85 100644 --- a/src/lib/transaction_snark/transaction_snark.ml +++ b/src/lib/transaction_snark/transaction_snark.ml @@ -891,8 +891,6 @@ module Make_str (A : Wire_types.Concrete) = struct module Permissions = struct type controller = Permissions.Auth_required.Checked.t - type txn_version = Mina_numbers.Txn_version.Checked.t - let edit_state : t -> controller = fun a -> a.data.permissions.edit_state @@ -911,9 +909,6 @@ module Make_str (A : Wire_types.Concrete) = struct let set_verification_key_auth : t -> controller = fun a -> fst a.data.permissions.set_verification_key - let set_verification_key_txn_version : t -> txn_version = - fun a -> snd a.data.permissions.set_verification_key - let set_zkapp_uri : t -> controller = fun a -> a.data.permissions.set_zkapp_uri @@ -1064,10 +1059,31 @@ module Make_str (A : Wire_types.Concrete) = struct let set_voting_for voting_for ({ data = a; hash } : t) : t = { data = { a with voting_for }; hash } + type txn_version = Mina_numbers.Txn_version.Checked.t + + let txn_version ({ data = a; _ } : t) = + snd a.permissions.set_verification_key + let permissions (a : t) = a.data.permissions - let set_permissions permissions ({ data = a; hash } : t) : t = - { data = { a with permissions }; hash } + let set_permissions_ignore_vk_txn_version + (permissions : Permissions.t) ({ data = a; hash } as t : t) : t = + let vk_txn_version = txn_version t in + let set_verification_key = + (fst permissions.set_verification_key, vk_txn_version) + in + let permissions = { permissions with set_verification_key } in + let data = { a with permissions } in + { data; hash } + + let set_txn_version_to_current ({ data = a; hash } : t) : t = + let set_verification_key = + ( fst a.permissions.set_verification_key + , Mina_numbers.Txn_version.current_checked ) + in + let permissions = { a.permissions with set_verification_key } in + let data = { a with permissions } in + { data; hash } end module Opt = struct