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

Don't check zkApp proofs in the snark if application will fail anyway #12490

Merged
merged 8 commits into from
Jan 26, 2023
Merged
6 changes: 4 additions & 2 deletions src/lib/mina_block/sample_precomputed_block.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ let sample_block_sexp =
0x0000000000000000000000000000000000000000000000000000000000000001)
(excess ((magnitude 0) (sgn Pos)))
(supply_increase ((magnitude 0) (sgn Pos))) (ledger 0)
(success true) (account_update_index 0) (failure_status_tbl ())))))
(success true) (account_update_index 0) (failure_status_tbl ())
(will_succeed true)))))
(timestamp 1668291220375)
(body_reference
"\255\242\2436c:`\178\"\194:/\242\132g\199\205r\251\197%\133\\\028\190\163#\236\221\247\178\157")))
Expand Down Expand Up @@ -490,7 +491,8 @@ let sample_block_json =
"ledger": "jw6bz2wud1N6itRUHZ5ypo3267stk4UgzkiuWtAMPRZo9g4Udyd",
"success": true,
"account_update_index": "0",
"failure_status_tbl": []
"failure_status_tbl": [],
"will_succeed": true
}
},
"timestamp": "1668291220375",
Expand Down
44 changes: 39 additions & 5 deletions src/lib/mina_ledger/sparse_ledger.ml
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,45 @@ let apply_zkapp_command_unchecked_with_states ~constraint_constants ~global_slot
}
, { local_state with ledger = !(local_state.ledger) } )
:: acc )
|> Result.map ~f:(fun (account_update_applied, states) ->
(* We perform a [List.rev] here to ensure that the states are in order
wrt. the zkapp_command that generated the states.
*)
(account_update_applied, List.rev states) )
|> Result.map ~f:(fun (account_update_applied, rev_states) ->
let module LS = Mina_transaction_logic.Zkapp_command_logic.Local_state
in
let module Applied = Transaction_applied.Zkapp_command_applied in
let states =
match rev_states with
| [] ->
[]
| final_state :: rev_states ->
(* Update the [will_succeed] of all *intermediate* states.
Note that the first and final states will always have
[will_succeed = true], so we must leave them unchanged.
*)
let will_succeed =
match account_update_applied.Applied.command.status with
| Applied ->
true
| Failed _ ->
false
in
(* We perform a manual [List.rev] here to ensure that the states
are in order wrt. the zkapp_command that generated the states.
*)
let rec go states rev_states =
match rev_states with
| [] ->
states
| [ initial_state ] ->
(* Skip the initial state *)
initial_state :: states
| (global_state, local_state) :: rev_states ->
go
( (global_state, { local_state with LS.will_succeed })
:: states )
rev_states
in
go [ final_state ] rev_states
in
(account_update_applied, states) )

let apply_transaction_logic f t x =
let open Or_error.Let_syntax in
Expand Down
16 changes: 14 additions & 2 deletions src/lib/mina_state/local_state.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ let display
; success
; account_update_index
; failure_status_tbl
; will_succeed
} :
t ) : display =
let open Kimchi_backend.Pasta.Basic in
Expand Down Expand Up @@ -58,6 +59,7 @@ let display
Transaction_status.Failure.Collection.to_display failure_status_tbl
|> Transaction_status.Failure.Collection.Display.to_yojson
|> Yojson.Safe.to_string
; will_succeed
}

let dummy : unit -> t =
Expand All @@ -73,6 +75,7 @@ let dummy : unit -> t =
; success = true
; account_update_index = Mina_numbers.Index.zero
; failure_status_tbl = []
; will_succeed = true
} )

let empty = dummy
Expand All @@ -87,8 +90,9 @@ let gen : t Quickcheck.Generator.t =
and call_stack = Call_stack_digest.gen
and token_id = Token_id.gen
and success = Bool.quickcheck_generator
and account_update_index =
Mina_numbers.Index.gen
and account_update_index = Mina_numbers.Index.gen
and will_succeed =
Bool.quickcheck_generator
(*
and failure_status =
let%bind failure = Transaction_status.Failure.gen in
Expand All @@ -106,6 +110,7 @@ let gen : t Quickcheck.Generator.t =
; success
; account_update_index
; failure_status_tbl = []
; will_succeed
}

let to_input
Expand All @@ -120,6 +125,7 @@ let to_input
; success
; account_update_index
; failure_status_tbl = _
; will_succeed
} :
t ) =
let open Random_oracle.Input.Chunked in
Expand All @@ -135,6 +141,7 @@ let to_input
; Ledger_hash.to_input ledger
; Mina_numbers.Index.to_input account_update_index
; packed (Mina_base.Util.field_of_bool success, 1)
; packed (Mina_base.Util.field_of_bool will_succeed, 1)
|]

module Checked = struct
Expand All @@ -160,6 +167,7 @@ module Checked = struct
~success:(f Impl.Boolean.Assert.( = ))
~account_update_index:(f !Mina_numbers.Index.Checked.Assert.equal)
~failure_status_tbl:(f (fun () () -> ()))
~will_succeed:(f Impl.Boolean.Assert.( = ))

let equal' (t1 : t) (t2 : t) =
let ( ! ) f x y = Impl.run_checked (f x y) in
Expand All @@ -175,6 +183,7 @@ module Checked = struct
~ledger:(f !Ledger_hash.equal_var) ~success:(f Impl.Boolean.equal)
~account_update_index:(f !Mina_numbers.Index.Checked.equal)
~failure_status_tbl:(f (fun () () -> Impl.Boolean.true_))
~will_succeed:(f Impl.Boolean.equal)

let to_input
({ stack_frame
Expand All @@ -188,6 +197,7 @@ module Checked = struct
; success
; account_update_index
; failure_status_tbl = _
; will_succeed
} :
t ) =
(* failure_status is the unit value, no need to represent it *)
Expand All @@ -204,6 +214,7 @@ module Checked = struct
; Ledger_hash.var_to_input ledger
; Mina_numbers.Index.Checked.to_input account_update_index
; packed ((success :> t), 1)
; packed ((will_succeed :> t), 1)
|]
end

Expand Down Expand Up @@ -233,6 +244,7 @@ let typ : (Checked.t, t) Impl.Typ.t =
; Boolean.typ
; Mina_numbers.Index.typ
; failure_status_tbl_typ
; Boolean.typ
]
~var_to_hlist:to_hlist ~var_of_hlist:of_hlist ~value_to_hlist:to_hlist
~value_of_hlist:of_hlist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module Local_state = struct
; success : 'bool
; account_update_index : 'length
; failure_status_tbl : 'failure_status_tbl
; will_succeed : 'bool
}
end

Expand Down
19 changes: 17 additions & 2 deletions src/lib/transaction_logic/mina_transaction_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,8 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
let may_use_token_inherited_from_parent (p : t) =
May_use_token.inherit_from_parent p.body.may_use_token

let check_authorization ~commitment:_ ~calls:_ (account_update : t) =
let check_authorization ~will_succeed:_ ~commitment:_ ~calls:_
(account_update : t) =
(* The transaction's validity should already have been checked before
this point.
*)
Expand Down Expand Up @@ -1739,6 +1740,12 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
in
(sequence_state', last_sequence_slot')

(** Apply a single zkApp transaction from beginning to end, applying an
accumulation function over the state for each account update.

CAUTION: If you use the intermediate local states, you MUST update the
[will_succeed] field to [false] if the [status] is [Failed].
*)
let apply_zkapp_command_unchecked_aux (type user_acc)
~(constraint_constants : Genesis_constants.Constraint_constants.t)
~(global_slot : Global_slot.t)
Expand Down Expand Up @@ -1793,14 +1800,22 @@ module Make (L : Ledger_intf.S) : S with type ledger := L.t = struct
; success = true
; account_update_index = Inputs.Index.zero
; failure_status_tbl = []
; will_succeed = true
} )
in
let user_acc = f init initial_state in
let%bind (start : Inputs.Global_state.t * _) =
let zkapp_command = Zkapp_command.zkapp_command c in
Or_error.try_with (fun () ->
M.start ~constraint_constants
{ zkapp_command; memo_hash = Signed_command_memo.hash c.memo }
{ zkapp_command
; memo_hash = Signed_command_memo.hash c.memo
; will_succeed =
(* It's always valid to set this value to true, and it will
have no effect outside of the snark.
*)
true
}
{ perform } initial_state )
in
let account_states_after_fee_payer =
Expand Down
38 changes: 34 additions & 4 deletions src/lib/transaction_logic/zkapp_command_logic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ module Local_state = struct
; success : 'bool
; account_update_index : 'length
; failure_status_tbl : 'failure_status_tbl
; will_succeed : 'bool
}
[@@deriving compare, equal, hash, sexp, yojson, fields, hlist]
end
Expand All @@ -230,6 +231,7 @@ module Local_state = struct
; bool
; length
; failure_status_tbl
; bool
]
~var_to_hlist:to_hlist ~var_of_hlist:of_hlist ~value_to_hlist:to_hlist
~value_of_hlist:of_hlist
Expand Down Expand Up @@ -337,7 +339,8 @@ module type Account_update_intf = sig
val implicit_account_creation_fee : t -> bool

val check_authorization :
commitment:transaction_commitment
will_succeed:bool
-> commitment:transaction_commitment
-> calls:call_forest
-> t
-> [ `Proof_verifies of bool ] * [ `Signature_verifies of bool ]
Expand Down Expand Up @@ -872,8 +875,11 @@ module Start_data = struct
[%%versioned
module Stable = struct
module V1 = struct
type ('zkapp_command, 'field) t =
{ zkapp_command : 'zkapp_command; memo_hash : 'field }
type ('zkapp_command, 'field, 'bool) t =
{ zkapp_command : 'zkapp_command
; memo_hash : 'field
; will_succeed : 'bool
}
[@@deriving sexp, yojson]
end
end]
Expand Down Expand Up @@ -1059,12 +1065,23 @@ module Make (Inputs : Inputs_intf) = struct
| `Compute _ ->
is_start'
in
let will_succeed =
match is_start with
| `Compute start_data ->
Bool.if_ is_start' ~then_:start_data.will_succeed
~else_:local_state.will_succeed
| `Yes start_data ->
start_data.will_succeed
| `No ->
local_state.will_succeed
in
let local_state =
{ local_state with
ledger =
Inputs.Ledger.if_ is_start'
~then_:(Inputs.Global_state.ledger global_state)
~else_:local_state.ledger
; will_succeed
}
in
let ( (account_update, remaining, call_stack)
Expand Down Expand Up @@ -1205,7 +1222,8 @@ module Make (Inputs : Inputs_intf) = struct
~then_:local_state.full_transaction_commitment
~else_:local_state.transaction_commitment
in
Inputs.Account_update.check_authorization ~commitment
Inputs.Account_update.check_authorization
~will_succeed:local_state.will_succeed ~commitment
~calls:account_update_forest account_update
in
assert_ ~pos:__POS__
Expand Down Expand Up @@ -1796,6 +1814,15 @@ module Make (Inputs : Inputs_intf) = struct
assert_with_failure_status_tbl ~pos:__POS__
((not is_start') ||| local_state.success)
local_state.failure_status_tbl) ;
(* If this is the last account update, and [will_succeed] is false, then
[success] must also be false.
*)
Bool.(
Assert.any ~pos:__POS__
[ not is_last_account_update
; local_state.will_succeed
; not local_state.success
]) ;
let global_state =
Global_state.set_ledger ~should_update:update_global_state global_state
local_state.ledger
Expand Down Expand Up @@ -1833,6 +1860,9 @@ module Make (Inputs : Inputs_intf) = struct
Amount.Signed.if_ is_last_account_update
~then_:Amount.(Signed.of_unsigned zero)
~else_:local_state.supply_increase
; will_succeed =
Bool.if_ is_last_account_update ~then_:Bool.true_
~else_:local_state.will_succeed
}
in
(global_state, local_state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let deploy_account_update_body : Account_update.Body.t =
; account = Accept
; valid_while = Ignore
}
; call_type = Call
; may_use_token = No
; use_full_commitment = true
; authorization_kind = Signature
}
Expand Down
Loading