Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 16 additions & 12 deletions src/app/zkapp_limits/zkapp_limits.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,35 @@
open Core_kernel

let main () =
let genesis_constants = Genesis_constants.Compiled.genesis_constants in
let cost_limit = genesis_constants.zkapp_transaction_cost_limit in
let max_event_elements = genesis_constants.max_event_elements in
let max_action_elements = genesis_constants.max_action_elements in
let values = List.init 20 ~f:Fn.id in
let Genesis_constants.
{ max_event_elements
; max_action_elements
; max_zkapp_segment_per_transaction
; _
} =
Genesis_constants.Compiled.genesis_constants
in
let values = List.init (1 + max_zkapp_segment_per_transaction) ~f:Fn.id in
printf "max field elements for events per transaction: %d\n"
max_event_elements ;
printf "max field elements for actions per transaction: %d\n"
max_action_elements ;
printf "All possible zkApp account update combinations:\n" ;
List.iter values ~f:(fun proofs ->
List.iter values ~f:(fun proof_segments ->
List.iter values ~f:(fun signed_single_segments ->
List.iter values ~f:(fun signed_pair_segments ->
let cost =
Mina_base.Zkapp_command.zkapp_cost ~proof_segments:proofs
Mina_base.Zkapp_command.zkapp_cost ~proof_segments
~signed_single_segments ~signed_pair_segments
~genesis_constants ()
in
if Float.(cost <. cost_limit) then
if cost <= max_zkapp_segment_per_transaction then
printf
"Proofs updates=%d Signed/None updates=%d Pairs of \
Signed/None updates=%d: Total account updates: %d Cost: %f \n\
Signed/None updates=%d: Total account updates: %d Cost: %d \n\
%!"
proofs signed_single_segments signed_pair_segments
(proofs + signed_single_segments + (signed_pair_segments * 2))
proof_segments signed_single_segments signed_pair_segments
( proof_segments + signed_single_segments
+ (signed_pair_segments * 2) )
cost ) ) )

let () = main ()
16 changes: 7 additions & 9 deletions src/lib/genesis_constants/genesis_constants.ml
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,11 @@ module T = struct
{ protocol : Protocol.Stable.Latest.t
; txpool_max_size : int
; num_accounts : int option
; zkapp_proof_update_cost : float
; zkapp_signed_single_update_cost : float
; zkapp_signed_pair_update_cost : float
; zkapp_transaction_cost_limit : float
; max_zkapp_segment_per_transaction : int
Copy link
Member Author

Choose a reason for hiding this comment

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

1 param to rule them all :)

(** The maximum number of segments allowed per zkapp command. A
segment is either: a proof, a signed single update, or a signed
pair update. Transactions with a number of segments equal to this
limit are valid. *)
; max_event_elements : int
; max_action_elements : int
; zkapp_cmd_limit_hardcap : int
Expand Down Expand Up @@ -425,11 +426,8 @@ module Make (Node_config : Node_config_intf.S) : S = struct
}
; txpool_max_size = pool_max_size
; num_accounts = None
; zkapp_proof_update_cost = Node_config.zkapp_proof_update_cost
; zkapp_signed_single_update_cost =
Node_config.zkapp_signed_single_update_cost
; zkapp_signed_pair_update_cost = Node_config.zkapp_signed_pair_update_cost
; zkapp_transaction_cost_limit = Node_config.zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction =
Node_config.max_zkapp_segment_per_transaction
; max_event_elements = Node_config.max_event_elements
; max_action_elements = Node_config.max_action_elements
; zkapp_cmd_limit_hardcap = Node_config.zkapp_cmd_limit_hardcap
Expand Down
15 changes: 3 additions & 12 deletions src/lib/genesis_ledger_helper/lib/genesis_ledger_helper_lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -563,18 +563,9 @@ let make_genesis_constants ~logger ~(default : Genesis_constants.t)
; txpool_max_size =
Option.value ~default:default.txpool_max_size
(config.daemon >>= fun cfg -> cfg.txpool_max_size)
; zkapp_proof_update_cost =
Option.value ~default:default.zkapp_proof_update_cost
(config.daemon >>= fun cfg -> cfg.zkapp_proof_update_cost)
; zkapp_signed_single_update_cost =
Option.value ~default:default.zkapp_signed_single_update_cost
(config.daemon >>= fun cfg -> cfg.zkapp_signed_single_update_cost)
; zkapp_signed_pair_update_cost =
Option.value ~default:default.zkapp_signed_pair_update_cost
(config.daemon >>= fun cfg -> cfg.zkapp_signed_pair_update_cost)
; zkapp_transaction_cost_limit =
Option.value ~default:default.zkapp_transaction_cost_limit
(config.daemon >>= fun cfg -> cfg.zkapp_transaction_cost_limit)
; max_zkapp_segment_per_transaction =
Option.value ~default:default.max_zkapp_segment_per_transaction
(config.daemon >>= fun cfg -> cfg.max_zkapp_segment_per_transaction)
; max_event_elements =
Option.value ~default:default.max_event_elements
(config.daemon >>= fun cfg -> cfg.max_event_elements)
Expand Down
54 changes: 37 additions & 17 deletions src/lib/mina_base/zkapp_command.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1309,16 +1309,33 @@ module Update_group = Make_update_group (struct
failwith "zkapp_segment_of_controls: Unsupported combination"
end)

let zkapp_cost ~proof_segments ~signed_single_segments ~signed_pair_segments
~(genesis_constants : Genesis_constants.t) () =
(*10.26*np + 10.08*n2 + 9.14*n1 < 69.45*)
let proof_cost = genesis_constants.zkapp_proof_update_cost in
let signed_pair_cost = genesis_constants.zkapp_signed_pair_update_cost in
let signed_single_cost = genesis_constants.zkapp_signed_single_update_cost in
Float.(
(proof_cost * of_int proof_segments)
+ (signed_pair_cost * of_int signed_pair_segments)
+ (signed_single_cost * of_int signed_single_segments))
(** [zkapp_cost ~proof_segments ~signed_single_segments ~signed_pair_segments]
returns the cost of a zkapp command having such constitution.

The cost of a zkapp command is defined as the number of segments it have in
the base layer.

This is because SNARK Coordinator schedules single base proof/merge to each
SNARK worker. These proofs form a B-ary tree, where B is Pickles' branching
factor, i.e. the number of proofs Pickles could be merged at once. Under
current configuration, B is 2.

The latency before us getting a final proof would be the latency from root
to any leaf node. Given we have sufficient workers available, possible proof
trees would be more or less a balanced binary tree, so with n segments, the
latency would of Theta(log_B n), assuming all kind proofs requires roughly
same time to proof.

to ensure the latency of receving final proof to be smaller than some cap,
we could equally just restrict number of leave segments. For example, If we
want the tree to have at most [L] layers, we just ensure the cost for any
zkapp_command to be at most [B^L].

WARN: this is only relevant after we merged SNARK worker rework PRs, please
Copy link
Member

Choose a reason for hiding this comment

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

I think this warning can be removed?

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed, rebasing onto compatible and removing it.

remove this warning if we've already done so.
*)
let zkapp_cost ~proof_segments ~signed_single_segments ~signed_pair_segments =
proof_segments + signed_single_segments + signed_pair_segments

(* Zkapp_command transactions are filtered using this predicate
- when adding to the transaction pool
Expand Down Expand Up @@ -1361,14 +1378,17 @@ let valid_size (type aux) ~(genesis_constants : Genesis_constants.t)
| Signed_pair ->
(proof_segments, signed_singles, signed_pairs + 1) )
in
let cost_limit = genesis_constants.zkapp_transaction_cost_limit in
let max_event_elements = genesis_constants.max_event_elements in
let max_action_elements = genesis_constants.max_action_elements in
let Genesis_constants.
{ max_event_elements
; max_action_elements
; max_zkapp_segment_per_transaction
; _
} =
genesis_constants
in
let zkapp_cost_within_limit =
Float.(
zkapp_cost ~proof_segments ~signed_single_segments ~signed_pair_segments
~genesis_constants ()
< cost_limit)
zkapp_cost ~proof_segments ~signed_single_segments ~signed_pair_segments
<= max_zkapp_segment_per_transaction
in
let valid_event_elements = num_event_elements <= max_event_elements in
let valid_action_elements = num_action_elements <= max_action_elements in
Expand Down
40 changes: 9 additions & 31 deletions src/lib/mina_compile_config/mina_compile_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ module Inputs = struct
; rpc_handshake_timeout_sec : float
; rpc_heartbeat_timeout_sec : float
; rpc_heartbeat_send_every_sec : float
; zkapp_proof_update_cost : float
; zkapp_signed_pair_update_cost : float
; zkapp_signed_single_update_cost : float
; zkapp_transaction_cost_limit : float
; max_zkapp_segment_per_transaction : int
; max_event_elements : int
; max_action_elements : int
; zkapp_cmd_limit_hardcap : int
Expand All @@ -47,10 +44,7 @@ type t =
; rpc_handshake_timeout : Time.Span.t
; rpc_heartbeat_timeout : Time.Span.t
; rpc_heartbeat_send_every : Time.Span.t
; zkapp_proof_update_cost : float
; zkapp_signed_pair_update_cost : float
; zkapp_signed_single_update_cost : float
; zkapp_transaction_cost_limit : float
; max_zkapp_segment_per_transaction : int
; max_event_elements : int
; max_action_elements : int
; zkapp_cmd_limit_hardcap : int
Expand Down Expand Up @@ -80,10 +74,7 @@ let make (inputs : Inputs.t) =
; rpc_heartbeat_timeout = Time.Span.of_sec inputs.rpc_heartbeat_timeout_sec
; rpc_heartbeat_send_every =
Time.Span.of_sec inputs.rpc_heartbeat_send_every_sec
; zkapp_proof_update_cost = inputs.zkapp_proof_update_cost
; zkapp_signed_pair_update_cost = inputs.zkapp_signed_pair_update_cost
; zkapp_signed_single_update_cost = inputs.zkapp_signed_single_update_cost
; zkapp_transaction_cost_limit = inputs.zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction = inputs.max_zkapp_segment_per_transaction
; max_event_elements = inputs.max_event_elements
; max_action_elements = inputs.max_action_elements
; network_id = inputs.network_id
Expand Down Expand Up @@ -115,11 +106,8 @@ let to_yojson t =
, `Float (Time.Span.to_sec t.rpc_heartbeat_timeout) )
; ( "rpc_heartbeat_send_every"
, `Float (Time.Span.to_sec t.rpc_heartbeat_send_every) )
; ("zkapp_proof_update_cost", `Float t.zkapp_proof_update_cost)
; ("zkapp_signed_pair_update_cost", `Float t.zkapp_signed_pair_update_cost)
; ( "zkapp_signed_single_update_cost"
, `Float t.zkapp_signed_single_update_cost )
; ("zkapp_transaction_cost_limit", `Float t.zkapp_transaction_cost_limit)
; ( "max_zkapp_segment_per_transaction"
, `Int t.max_zkapp_segment_per_transaction )
; ("max_event_elements", `Int t.max_event_elements)
; ("max_action_elements", `Int t.max_action_elements)
; ("network_id", `String t.network_id)
Expand Down Expand Up @@ -147,12 +135,8 @@ module Compiled = struct
; rpc_handshake_timeout_sec = Node_config.rpc_handshake_timeout_sec
; rpc_heartbeat_timeout_sec = Node_config.rpc_heartbeat_timeout_sec
; rpc_heartbeat_send_every_sec = Node_config.rpc_heartbeat_send_every_sec
; zkapp_proof_update_cost = Node_config.zkapp_proof_update_cost
; zkapp_signed_pair_update_cost =
Node_config.zkapp_signed_pair_update_cost
; zkapp_signed_single_update_cost =
Node_config.zkapp_signed_single_update_cost
; zkapp_transaction_cost_limit = Node_config.zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction =
Node_config.max_zkapp_segment_per_transaction
; max_event_elements = Node_config.max_event_elements
; max_action_elements = Node_config.max_action_elements
; network_id = Node_config.network
Expand Down Expand Up @@ -188,14 +172,8 @@ module For_unit_tests = struct
Node_config_for_unit_tests.rpc_heartbeat_timeout_sec
; rpc_heartbeat_send_every_sec =
Node_config_for_unit_tests.rpc_heartbeat_send_every_sec
; zkapp_proof_update_cost =
Node_config_for_unit_tests.zkapp_proof_update_cost
; zkapp_signed_pair_update_cost =
Node_config_for_unit_tests.zkapp_signed_pair_update_cost
; zkapp_signed_single_update_cost =
Node_config_for_unit_tests.zkapp_signed_single_update_cost
; zkapp_transaction_cost_limit =
Node_config_for_unit_tests.zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction =
Node_config_for_unit_tests.max_zkapp_segment_per_transaction
; max_event_elements = Node_config_for_unit_tests.max_event_elements
; max_action_elements = Node_config_for_unit_tests.max_action_elements
; network_id = Node_config_for_unit_tests.network
Expand Down
8 changes: 1 addition & 7 deletions src/lib/node_config/intf/node_config_intf.mli
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@ end

(* It's stupid that this exists. TODO: Remove and make configurable. *)
module type Unconfigurable_constants = sig
val zkapp_proof_update_cost : float

val zkapp_signed_pair_update_cost : float

val zkapp_signed_single_update_cost : float

val zkapp_transaction_cost_limit : float
val max_zkapp_segment_per_transaction : int

val max_event_elements : int

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
(* FIXME: These should be configurable. *)

(** limits on Zkapp_command.t size
10.26*np + 10.08*n2 + 9.14*n1 < 69.45
where np: number of single proof updates
n2: number of pairs of signed/no-auth update
n1: number of single signed/no-auth update
and their coefficients representing the cost
The formula was generated based on benchmarking data conducted on bare
metal i9 processor with room to include lower spec.
69.45 was the total time for a combination of updates that was considered
acceptable.
The method used to estimate the cost was linear least squares.
*)

let zkapp_proof_update_cost = 10.26

let zkapp_signed_pair_update_cost = 10.08

let zkapp_signed_single_update_cost = 9.14

let zkapp_transaction_cost_limit = 69.45
let max_zkapp_segment_per_transaction = 16

let max_event_elements = 100

Expand Down
35 changes: 7 additions & 28 deletions src/lib/runtime_config/runtime_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,7 @@ module Json_layout = struct
type t =
{ txpool_max_size : int option [@default None]
; peer_list_url : string option [@default None]
; zkapp_proof_update_cost : float option [@default None]
; zkapp_signed_single_update_cost : float option [@default None]
; zkapp_signed_pair_update_cost : float option [@default None]
; zkapp_transaction_cost_limit : float option [@default None]
; max_zkapp_segment_per_transaction : int option [@default None]
; max_event_elements : int option [@default None]
; max_action_elements : int option [@default None]
; zkapp_cmd_limit_hardcap : int option [@default None]
Expand Down Expand Up @@ -1271,10 +1268,7 @@ module Daemon = struct
type t = Json_layout.Daemon.t =
{ txpool_max_size : int option
; peer_list_url : string option
; zkapp_proof_update_cost : float option [@default None]
; zkapp_signed_single_update_cost : float option [@default None]
; zkapp_signed_pair_update_cost : float option [@default None]
; zkapp_transaction_cost_limit : float option [@default None]
; max_zkapp_segment_per_transaction : int option [@default None]
; max_event_elements : int option [@default None]
; max_action_elements : int option [@default None]
; zkapp_cmd_limit_hardcap : int option [@default None]
Expand Down Expand Up @@ -1303,18 +1297,9 @@ module Daemon = struct
{ txpool_max_size =
opt_fallthrough ~default:t1.txpool_max_size t2.txpool_max_size
; peer_list_url = opt_fallthrough ~default:t1.peer_list_url t2.peer_list_url
; zkapp_proof_update_cost =
opt_fallthrough ~default:t1.zkapp_proof_update_cost
t2.zkapp_proof_update_cost
; zkapp_signed_single_update_cost =
opt_fallthrough ~default:t1.zkapp_signed_single_update_cost
t2.zkapp_signed_single_update_cost
; zkapp_signed_pair_update_cost =
opt_fallthrough ~default:t1.zkapp_signed_pair_update_cost
t2.zkapp_signed_pair_update_cost
; zkapp_transaction_cost_limit =
opt_fallthrough ~default:t1.zkapp_transaction_cost_limit
t2.zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction =
opt_fallthrough ~default:t1.max_zkapp_segment_per_transaction
t2.max_zkapp_segment_per_transaction
; max_event_elements =
opt_fallthrough ~default:t1.max_event_elements t2.max_event_elements
; max_action_elements =
Expand Down Expand Up @@ -1343,10 +1328,7 @@ module Daemon = struct
let gen =
let open Quickcheck.Generator.Let_syntax in
let%bind txpool_max_size = Int.gen_incl 0 1000 in
let%bind zkapp_proof_update_cost = Float.gen_incl 0.0 100.0 in
let%bind zkapp_signed_single_update_cost = Float.gen_incl 0.0 100.0 in
let%bind zkapp_signed_pair_update_cost = Float.gen_incl 0.0 100.0 in
let%bind zkapp_transaction_cost_limit = Float.gen_incl 0.0 100.0 in
let%bind max_zkapp_segment_per_transaction = Int.gen_incl 0 50 in
Copy link
Member Author

Choose a reason for hiding this comment

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

Unsure about these generators

Copy link
Member

@cjjdespres cjjdespres Sep 30, 2025

Choose a reason for hiding this comment

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

I am as well. The old generator could generate a config with 0 cost on the three zkapp components. I think that would mean no limit on the number of zkapp proof or signed updates.

Where is it used?

let%bind max_event_elements = Int.gen_incl 0 100 in
let%bind zkapp_cmd_limit_hardcap = Int.gen_incl 0 1000 in
let%bind minimum_user_command_fee =
Expand All @@ -1355,10 +1337,7 @@ module Daemon = struct
let%map max_action_elements = Int.gen_incl 0 1000 in
{ txpool_max_size = Some txpool_max_size
; peer_list_url = None
; zkapp_proof_update_cost = Some zkapp_proof_update_cost
; zkapp_signed_single_update_cost = Some zkapp_signed_single_update_cost
; zkapp_signed_pair_update_cost = Some zkapp_signed_pair_update_cost
; zkapp_transaction_cost_limit = Some zkapp_transaction_cost_limit
; max_zkapp_segment_per_transaction = Some max_zkapp_segment_per_transaction
; max_event_elements = Some max_event_elements
; max_action_elements = Some max_action_elements
; zkapp_cmd_limit_hardcap = Some zkapp_cmd_limit_hardcap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ let create ~(test_config : Test_config.t) ~(genesis_ledger : Genesis_ledger.t) =
Some
{ txpool_max_size = Some test_config.txpool_max_size
; peer_list_url = None
; zkapp_proof_update_cost = None
; zkapp_signed_single_update_cost = None
; zkapp_signed_pair_update_cost = None
; zkapp_transaction_cost_limit = None
; max_zkapp_segment_per_transaction = None
; max_event_elements = None
; max_action_elements = None
; zkapp_cmd_limit_hardcap = None
Expand Down