Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check verification key hash in apply #12498

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/app/cli/src/init/transaction_snark_profiler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,11 @@ let profile_zkapps ~verifier ledger zkapp_commands =
let v_start_time = Time.now () in
let%bind res =
Verifier.verify_commands verifier
[ User_command.to_verifiable ~find_vk:(Zkapp_command.Verifiable.find_vk_via_ledger ~ledger ~get:Mina_ledger.Ledger.get
~location_of_account:Mina_ledger.Ledger.location_of_account)
[ User_command.to_verifiable
~find_vk:
(Zkapp_command.Verifiable.find_vk_via_ledger ~ledger
~get:Mina_ledger.Ledger.get
~location_of_account:Mina_ledger.Ledger.location_of_account )
(Zkapp_command zkapp_command)
|> Or_error.ok_exn
]
Expand Down
5 changes: 2 additions & 3 deletions src/lib/mina_ledger/ledger.ml
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,8 @@ let%test_unit "tokens test" =
(-(4 * account_creation_fee)) )
[]
; mk_node
(mk_account_update_body
(Proof (Zkapp_account.dummy_vk_hash ()))
Call token_owner Token_id.default (3 * account_creation_fee) )
(mk_account_update_body Signature Call token_owner Token_id.default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use a test zkapp here instead of changing the authorization? or write another similar test with Proof auth?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bug in this test, if we use Proof, because the corresponding ledger account has None for the zkapp field, hence no vk hash, so the new vk hash check fails.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm able to patch the ledger so the token funder has a zkapp with the dummy verification key, allowing Proof for this sub-test. (It would require a bit more change to do the same for the token owner.)

(3 * account_creation_fee) )
[]
]
in
Expand Down
22 changes: 22 additions & 0 deletions src/lib/transaction_logic/mina_transaction_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,8 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
type t = Snark_params.Tick.Field.t

let if_ = value_if

let equal = Snark_params.Tick.Field.equal
end

module Bool = struct
Expand Down Expand Up @@ -1214,6 +1216,12 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
let if_ = value_if
end

module Verification_key_hash = struct
type t = Field.t option

let equal vk1 vk2 = Option.equal Field.equal vk1 vk2
end

module Actions = struct
type t = Zkapp_account.Actions.t

Expand Down Expand Up @@ -1349,6 +1357,13 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
let set_verification_key verification_key (a : t) =
set_zkapp a ~f:(fun zkapp -> { zkapp with verification_key })

let verification_key_hash (a : t) =
match a.zkapp with
| None ->
None
| Some zkapp ->
Option.map zkapp.verification_key ~f:With_hash.hash

let last_sequence_slot (a : t) = (get_zkapp a).last_sequence_slot

let set_last_sequence_slot last_sequence_slot (a : t) =
Expand Down Expand Up @@ -1494,6 +1509,13 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
| Proof _ | None_given ->
false

let verification_key_hash (p : t) =
match p.body.authorization_kind with
| Proof vk_hash ->
Some vk_hash
| _ ->
None

module Update = struct
open Zkapp_basic

Expand Down
42 changes: 35 additions & 7 deletions src/lib/transaction_logic/zkapp_command_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ module type Global_slot_intf = sig
val equal : t -> t -> bool
end

module type Verification_key_hash_intf = sig
type t

type bool

val equal : t -> t -> bool
end

module type Timing_intf = sig
include Iffable

Expand Down Expand Up @@ -304,6 +312,8 @@ module type Account_update_intf = sig

type nonce

type verification_key_hash

type _ or_ignore

val balance_change : t -> signed_amount
Expand Down Expand Up @@ -332,6 +342,8 @@ module type Account_update_intf = sig

val is_proved : t -> bool

val verification_key_hash : t -> verification_key_hash

module Update : sig
type _ set_or_keep

Expand Down Expand Up @@ -543,10 +555,10 @@ module type Account_intf = sig

val set_receipt_chain_hash : t -> receipt_chain_hash -> t

(** Fill the snapp field of the account if it's currently [None] *)
(** Fill the zkapp field of the account if it's currently [None] *)
val make_zkapp : t -> t

(** If the current account has no snapp fields set, reset its snapp field to
(** If the current account has no zkApp fields set, reset its zkapp field to
[None].
*)
val unmake_zkapp : t -> t
Expand All @@ -569,6 +581,10 @@ module type Account_intf = sig

val set_verification_key : verification_key -> t -> t

type verification_key_hash

val verification_key_hash : t -> verification_key_hash

val last_sequence_slot : t -> global_slot

val set_last_sequence_slot : global_slot -> t -> t
Expand Down Expand Up @@ -690,8 +706,6 @@ module type Inputs_intf = sig
module Timing :
Timing_intf with type bool := Bool.t and type global_slot := Global_slot.t

module Verification_key : Iffable with type bool := Bool.t

module Zkapp_uri : Iffable with type bool := Bool.t

module Token_symbol : Iffable with type bool := Bool.t
Expand All @@ -704,6 +718,10 @@ module type Inputs_intf = sig
and type transaction_commitment := Transaction_commitment.t
and type index := Index.t)

and Verification_key : (Iffable with type bool := Bool.t)
and Verification_key_hash :
(Verification_key_hash_intf with type bool := Bool.t)

and Account :
(Account_intf
with type Permissions.controller := Controller.t
Expand All @@ -714,6 +732,7 @@ module type Inputs_intf = sig
and type global_slot := Global_slot.t
and type field := Field.t
and type verification_key := Verification_key.t
and type verification_key_hash := Verification_key_hash.t
and type zkapp_uri := Zkapp_uri.t
and type token_symbol := Token_symbol.t
and type public_key := Public_key.t
Expand All @@ -735,6 +754,7 @@ module type Inputs_intf = sig
and type public_key := Public_key.t
and type nonce := Nonce.t
and type account_id := Account_id.t
and type verification_key_hash := Verification_key_hash.t
and type Update.timing := Timing.t
and type 'a Update.set_or_keep := 'a Set_or_keep.t
and type Update.field := Field.t
Expand Down Expand Up @@ -884,7 +904,7 @@ module Make (Inputs : Inputs_intf) = struct
}

let get_next_account_update (current_forest : Stack_frame.t)
(* The stack for the most recent snapp *)
(* The stack for the most recent zkApp *)
(call_stack : Call_stack.t) (* The partially-completed parent stacks *)
: get_next_account_update_result =
(* If the current stack is complete, 'return' to the previous
Expand Down Expand Up @@ -1142,6 +1162,14 @@ module Make (Inputs : Inputs_intf) = struct
(Account_update.token_id account_update)
(a, inclusion_proof)
in
let matching_verification_key_hashes =
Inputs.Bool.(
(not (Account_update.is_proved account_update))
||| Verification_key_hash.equal
(Account.verification_key_hash a)
(Account_update.verification_key_hash account_update))
in
assert_ ~pos:__POS__ matching_verification_key_hashes ;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you call Local_state.add_check instead of raising. We also need a new failure to identify this error

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

let local_state =
h.perform
(Check_account_precondition
Expand Down Expand Up @@ -1334,11 +1362,11 @@ module Make (Inputs : Inputs_intf) = struct
(* The [proved_state] tracks whether the app state has been entirely
determined by proofs ([true] if so), to allow zkApp authors to be
confident that their initialization logic has been run, rather than
some malicious deployer instantiating the snapp in an account with
some malicious deployer instantiating the zkApp in an account with
some fake non-initial state.
The logic here is:
* if the state is unchanged, keep the previous value;
* if the state has been entriely replaced, and the authentication
* if the state has been entirely replaced, and the authentication
was a proof, the state has been 'proved' and [proved_state] is set
to [true];
* if the state has been partially updated by a proof, the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,7 @@ let%test_module "multisig_account" =
}
; use_full_commitment = false
; caller = Call
; authorization_kind =
Proof (Mina_base.Zkapp_account.dummy_vk_hash ())
; authorization_kind = Proof (With_hash.hash vk)
}
; authorization = Proof Mina_base.Proof.transaction_dummy
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ let%test_module "Sequence events test" =
end

let test_zkapp_command ?expected_failure ?state_body ?(fee_payer_nonce = 0)
~ledger zkapp_command =
~ledger zkapp_command0 =
let zkapp_command =
Zkapps_examples.patch_verification_key_hashes ~ledger zkapp_command0
in
let memo = Signed_command_memo.empty in
let transaction_commitment : Zkapp_command.Transaction_commitment.t =
let account_updates_hash =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ let%test_module "Add events test" =
~handler:(Zkapps_add_events.update_events_handler events) )
end

let test_zkapp_command ?expected_failure zkapp_command =
let test_zkapp_command ?expected_failure zkapp_command0 =
let zkapp_command =
Zkapps_examples.patch_verification_key_hashes zkapp_command0
in
let memo = Signed_command_memo.empty in
let transaction_commitment : Zkapp_command.Transaction_commitment.t =
let account_updates_hash =
Expand Down
7 changes: 5 additions & 2 deletions src/lib/transaction_snark/test/zkapps_examples/calls/calls.ml
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,10 @@ let%test_module "Composability test" =
|> fst
end

let test_zkapp_command ?expected_failure zkapp_command =
let memo = Signed_command_memo.empty in
let test_zkapp_command ?expected_failure zkapp_command0 =
let zkapp_command =
Zkapps_examples.patch_verification_key_hashes zkapp_command0
in
let transaction_commitment : Zkapp_command.Transaction_commitment.t =
(* TODO: This is a pain. *)
let account_updates_hash =
Expand All @@ -229,6 +231,7 @@ let%test_module "Composability test" =
; authorization = Signature.dummy
}
in
let memo = Signed_command_memo.empty in
let memo_hash = Signed_command_memo.hash memo in
let full_commitment =
Zkapp_command.Transaction_commitment.create_complete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ let account_updates =
[]
|> Zkapp_command.Call_forest.cons_tree account_update
|> Zkapp_command.Call_forest.cons deploy_account_update
|> Zkapps_examples.patch_verification_key_hashes

let memo = Signed_command_memo.empty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ let%test_module "Initialize state test" =
~handler:(Zkapps_initialize_state.update_state_handler new_state) )
end

let test_zkapp_command ?expected_failure zkapp_command =
let test_zkapp_command ?expected_failure zkapp_command0 =
let zkapp_command =
Zkapps_examples.patch_verification_key_hashes zkapp_command0
in
let memo = Signed_command_memo.empty in
let transaction_commitment : Zkapp_command.Transaction_commitment.t =
(* TODO: This is a pain. *)
Expand Down
13 changes: 13 additions & 0 deletions src/lib/transaction_snark/transaction_snark.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,12 @@ module Make_str (A : Wire_types.Concrete) = struct
Zkapp_basic.Flagged_option.if_ ~if_:Data_as_hash.if_ b ~then_ ~else_
end

module Verification_key_hash = struct
type t = Field.t

let equal = Field.equal
end

module Actions = struct
type t = Zkapp_account.Actions.var

Expand Down Expand Up @@ -1311,6 +1317,10 @@ module Make_str (A : Wire_types.Concrete) = struct
; hash
}

let verification_key_hash (a : t) : Verification_key_hash.t =
verification_key a |> Zkapp_basic.Flagged_option.data
|> Data_as_hash.hash

let last_sequence_slot (a : t) = a.data.zkapp.last_sequence_slot

let set_last_sequence_slot last_sequence_slot ({ data = a; hash } : t)
Expand Down Expand Up @@ -1915,6 +1925,9 @@ module Make_str (A : Wire_types.Concrete) = struct
let is_signed ({ account_update; _ } : t) =
account_update.data.authorization_kind.is_signed

let verification_key_hash ({ account_update; _ } : t) =
account_update.data.authorization_kind.verification_key_hash

module Update = struct
open Zkapp_basic

Expand Down
2 changes: 2 additions & 0 deletions src/lib/zkapps_examples/dune
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
kimchi_pasta
kimchi_backend.pasta.basic
mina_base
mina_base.import
mina_ledger
pickles
pickles.backend
pickles_types
Expand Down
46 changes: 44 additions & 2 deletions src/lib/zkapps_examples/zkapps_examples.ml
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,10 @@ module Account_update_under_construction = struct
; account = Account_condition.to_predicate t.account_condition
}
; use_full_commitment = Boolean.false_
; caller = t.caller
; caller =
t.caller
(* the vk hash is a dummy, to be patched with `patch_verification_key_hashes`, below *)
; authorization_kind =
(* TODO: is there a valid vk hash available? *)
{ is_signed = Boolean.false_
; is_proved = Boolean.true_
; verification_key_hash = Field.zero
Expand Down Expand Up @@ -597,3 +598,44 @@ let compile :
go provers
in
(tag, cache_handle, proof, provers)

(* replace dummy vk hashes in account updates *)
let patch_verification_key_hashes ?ledger account_updates =
(* update vk hashes if Set in an account update *)
let vk_hash_tbl : Impl.field Public_key.Compressed.Table.t =
Public_key.Compressed.Table.create ()
in
(* if ledger provided, add vk hashes from those accounts *)
Option.iter ledger ~f:(fun (ledger : Mina_ledger.Ledger.t) ->
Mina_ledger.Ledger.iteri ledger ~f:(fun _n acct ->
Option.iter acct.zkapp ~f:(fun zkapp ->
Option.iter zkapp.verification_key ~f:(fun vk ->
let pk : Public_key.Compressed.t = acct.public_key in
Public_key.Compressed.Table.set vk_hash_tbl ~key:pk
~data:(With_hash.hash vk) ) ) ) ) ;
Zkapp_command.Call_forest.map account_updates
~f:(fun (acct_update : Account_update.t) ->
let pk = acct_update.body.public_key in
let acct_update' =
match Public_key.Compressed.Table.find vk_hash_tbl pk with
| None ->
acct_update
| Some vk_hash -> (
match acct_update.body.authorization_kind with
| Proof _ ->
{ acct_update with
body =
{ acct_update.body with authorization_kind = Proof vk_hash }
}
| Signature | None_given ->
acct_update )
in
(* add entry for subsequent updates *)
( match acct_update.body.update.verification_key with
| Set vk ->
let vk_hash = With_hash.hash vk in
Public_key.Compressed.Table.set vk_hash_tbl ~key:pk ~data:vk_hash
| Keep ->
() ) ;
acct_update' )
|> Zkapp_command.Call_forest.accumulate_hashes'