diff --git a/manifest/main.ml b/manifest/main.ml index ce46de217aa1f6b416f1eb711bdb978c5e372588..04823be55c2415f28cd5ce4452cfc26a3134e818 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -234,7 +234,9 @@ let ometrics = opam_only "ometrics" V.(at_least "0.2.1") let ppx_expect = inline_tests_backend (external_lib "ppx_expect" V.True) -let plonk = external_lib "tezos-plonk" V.(at_least "0.1.0") +let plompiler = external_lib "tezos-plompiler" V.(at_least "0.1.2") + +let plonk = external_lib "tezos-plonk" V.(at_least "0.1.2") let ptime = external_lib ~js_compatible:true "ptime" V.(at_least "1.0.0") @@ -3464,6 +3466,7 @@ end = struct ("refutation_game_pbt", N.(number == 013)); ("test_refutation_game", N.(number >= 014)); ("test_carbonated_map", N.(number >= 013)); + ("test_zk_rollup_encoding", N.(number >= 015)); ]) ~synopsis:"Tezos/Protocol: tests for economic-protocol definition" ~path:(path // "lib_protocol/test/pbt") @@ -4040,6 +4043,7 @@ module Protocol = Protocol octez_protocol_environment; plugin |> if_some |> open_; octez_shell_services |> open_; + plompiler |> if_ N.(number >= 015); ] in let _plugin_tests = diff --git a/opam/tezos-alpha-test-helpers.opam b/opam/tezos-alpha-test-helpers.opam index 4069500c760c8fdc8a90d896a4fc25e59de22005..524c3b558b80b29accfe766c5f26e45d04cf5e0a 100644 --- a/opam/tezos-alpha-test-helpers.opam +++ b/opam/tezos-alpha-test-helpers.opam @@ -20,6 +20,7 @@ depends: [ "tezos-protocol-environment" "tezos-protocol-plugin-alpha" "tezos-shell-services" + "tezos-plompiler" { >= "0.1.2" } ] build: [ ["rm" "-r" "vendors"] diff --git a/opam/tezos-protocol-environment.opam b/opam/tezos-protocol-environment.opam index 43a55f3f61059923937eb90a65498b008a5ba11d..c90865fb0541996f482fcdcb3fc54a437976d12a 100644 --- a/opam/tezos-protocol-environment.opam +++ b/opam/tezos-protocol-environment.opam @@ -16,7 +16,7 @@ depends: [ "tezos-scoru-wasm" "data-encoding" { >= "0.6" & < "0.7" } "bls12-381" { >= "4.0.0" & < "4.1.0" } - "tezos-plonk" { >= "0.1.0" } + "tezos-plonk" { >= "0.1.2" } "zarith" { >= "1.12" & < "1.13" } "zarith_stubs_js" "tezos-crypto-dal" diff --git a/src/proto_alpha/bin_sc_rollup_node/daemon.ml b/src/proto_alpha/bin_sc_rollup_node/daemon.ml index fb05321ffc40ae814d7cb34177a87934e9293ced..8a96bc9b0a736ebeb35d5c54a60c4dacfc7a17fc 100644 --- a/src/proto_alpha/bin_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/bin_sc_rollup_node/daemon.ml @@ -122,7 +122,8 @@ module Make (PVM : Pvm.S) = struct | Tx_rollup_submit_batch _ | Tx_rollup_commit _ | Tx_rollup_return_bond _ | Tx_rollup_finalize_commitment _ | Tx_rollup_remove_commitment _ | Tx_rollup_rejection _ | Tx_rollup_dispatch_tickets _ | Transfer_ticket _ - | Dal_publish_slot_header _ | Sc_rollup_originate _ -> + | Dal_publish_slot_header _ | Sc_rollup_originate _ + | Zk_rollup_origination _ -> false in if not (is_for_my_rollup operation) then return_unit diff --git a/src/proto_alpha/bin_sc_rollup_node/injector.ml b/src/proto_alpha/bin_sc_rollup_node/injector.ml index 484e2fc263131dcd94408ef0165f6748b7f05a38..6818d6317b57700430358dccf965b3e80f25d07e 100644 --- a/src/proto_alpha/bin_sc_rollup_node/injector.ml +++ b/src/proto_alpha/bin_sc_rollup_node/injector.ml @@ -137,7 +137,7 @@ module Parameters : | Tx_rollup_rejection _ | Tx_rollup_dispatch_tickets _ | Transfer_ticket _ | Dal_publish_slot_header _ | Sc_rollup_originate _ | Sc_rollup_execute_outbox_message _ | Sc_rollup_recover_bond _ - | Sc_rollup_dal_slot_subscribe _ -> + | Sc_rollup_dal_slot_subscribe _ | Zk_rollup_origination _ -> (* These operations should never be handled by this injector *) assert false diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index d336b485d1b06585eddbb1b7fc3aadda4ee4e797..56832cd849fa1179812e0e13b3ed99312eedd4b5 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -335,7 +335,8 @@ let estimated_gas_single (type kind) | Sc_rollup_timeout_result {consumed_gas; _} | Sc_rollup_execute_outbox_message_result {consumed_gas; _} | Sc_rollup_recover_bond_result {consumed_gas; _} - | Sc_rollup_dal_slot_subscribe_result {consumed_gas; _} -> + | Sc_rollup_dal_slot_subscribe_result {consumed_gas; _} + | Zk_rollup_origination_result {consumed_gas; _} -> Ok consumed_gas) | Skipped _ -> error_with "Cannot estimate gas of skipped operation" @@ -414,7 +415,8 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size | Sc_rollup_cement_result _ | Sc_rollup_publish_result _ | Sc_rollup_refute_result _ | Sc_rollup_timeout_result _ | Sc_rollup_recover_bond_result _ - | Sc_rollup_dal_slot_subscribe_result _ -> + | Sc_rollup_dal_slot_subscribe_result _ | Zk_rollup_origination_result _ + -> Ok Z.zero) | Skipped _ -> error_with "Cannot estimate storage of skipped operation" @@ -502,7 +504,8 @@ let originated_contracts_single (type kind) | Sc_rollup_publish_result _ | Sc_rollup_refute_result _ | Sc_rollup_timeout_result _ | Sc_rollup_execute_outbox_message_result _ | Sc_rollup_recover_bond_result _ - | Sc_rollup_dal_slot_subscribe_result _ -> + | Sc_rollup_dal_slot_subscribe_result _ | Zk_rollup_origination_result _ + -> Ok []) | Skipped _ -> error_with "Cannot know originated contracts of skipped operation" diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index d6dd019c50fdf90afb481d84a828dd4b2f528b29..635c3da9afdb74a14c5405c708316ee7d4a67e81 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -412,6 +412,8 @@ let pp_manager_operation_content (type kind) source ppf "Data availability slot header publishing:@,Slot: %a" Dal.Slot.pp slot + | Zk_rollup_origination _ -> + Format.fprintf ppf "Zk rollup origination:@,From: %a" Contract.pp source let pp_balance_updates ppf balance_updates = let open Receipt in @@ -787,6 +789,14 @@ let pp_manager_operation_contents_result ppf op_result = pp_balance_updates ppf balance_updates ; pp_consumed_gas ppf consumed_gas in + let pp_zk_rollup_origination_result + (Zk_rollup_origination_result + {consumed_gas; originated_zk_rollup; size = _; balance_updates}) = + pp_consumed_gas ppf consumed_gas ; + Format.fprintf ppf "@,Address: %a" Zk_rollup.Address.pp originated_zk_rollup ; + pp_balance_updates ppf balance_updates + in + let manager_operation_name (type kind) (result : kind successful_manager_operation_result) = match result with @@ -824,6 +834,7 @@ let pp_manager_operation_contents_result ppf op_result = "data availability slot subscription" | Dal_publish_slot_header_result _ -> "data availability slot header publishing" + | Zk_rollup_origination_result _ -> "zk rollup originate" in let pp_manager_operation_contents_result (type kind) ppf (result : kind successful_manager_operation_result) = @@ -865,6 +876,7 @@ let pp_manager_operation_contents_result ppf op_result = pp_sc_rollup_dal_slot_subscribe_result op | Dal_publish_slot_header_result _ as op -> pp_dal_publish_slot_header_result op + | Zk_rollup_origination_result _ as op -> pp_zk_rollup_origination_result op in pp_operation_result ~operation_name:manager_operation_name diff --git a/src/proto_alpha/lib_injector/l1_operation.ml b/src/proto_alpha/lib_injector/l1_operation.ml index e426875631cb4fd615e8b39f7aa04243d51403ea..b2630b179ca22c3eb5f62c3f52fc473f9db39aff 100644 --- a/src/proto_alpha/lib_injector/l1_operation.ml +++ b/src/proto_alpha/lib_injector/l1_operation.ml @@ -105,6 +105,7 @@ module Manager_operation = struct sc_rollup_execute_outbox_message_case | Sc_rollup_recover_bond _ -> sc_rollup_recover_bond_case | Sc_rollup_dal_slot_subscribe _ -> sc_rollup_dal_slot_subscribe_case + | Zk_rollup_origination _ -> zk_rollup_origination_case let pp_kind ppf op = let open Operation.Encoding.Manager_operations in diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 3394195ddb7eeb4dbf4b2a2ab9c954c1faabe408..ad36f967164fd44f7a048790065d885aca401264 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -239,6 +239,7 @@ let constants_mainnet = timeout_period_in_blocks = sc_rollup_timeout_period_in_blocks; max_number_of_stored_cemented_commitments = 5; }); + zk_rollup = {enable = false; min_pending_to_process = 10}; } let default_dal_sandbox = diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 97a71eb9497f459ce75710a907f54331d6c4bd43..0ce62ae160320fcab1b74956b74d4d24f67dc606 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -80,6 +80,12 @@ "Dal_endorsement_repr", "Dal_errors_repr", + "Zk_rollup_scalar", + "Zk_rollup_repr", + "Zk_rollup_state_repr", + "Zk_rollup_account_repr", + "Zk_rollup_operation_repr", + "Bond_id_repr", "Vote_repr", "Liquidity_baking_repr", @@ -120,6 +126,8 @@ "Voting_period_storage", "Cache_repr", + "Zk_rollup_storage", + "Contract_delegate_storage", "Stake_storage", "Contract_storage", @@ -214,6 +222,7 @@ "Sc_rollup_operations", "Dal_apply", + "Zk_rollup_apply", "Baking", "Validate_errors", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 4122c70d07848cab16a552d7d623a5aba91a1c16..51df1bab87ced7e5af0a73f8e9d6d95b67a5b073 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -113,6 +113,15 @@ module Dal = struct end module Dal_errors = Dal_errors_repr + +module Zk_rollup = struct + include Zk_rollup_repr + module State = Zk_rollup_state_repr + module Account = Zk_rollup_account_repr + module Operation = Zk_rollup_operation_repr + include Zk_rollup_storage +end + module Entrypoint = Entrypoint_repr include Operation_repr diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9c92eeb56d264e9eb2134a25ae4432b31ab4e217..b031481dd8b2251376f2fbd3307e7b4bdb88a652 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -819,6 +819,8 @@ module Constants : sig max_number_of_stored_cemented_commitments : int; } + type zk_rollup = {enable : bool; min_pending_to_process : int} + type t = { preserved_cycles : int; blocks_per_cycle : int32; @@ -862,6 +864,7 @@ module Constants : sig tx_rollup : tx_rollup; dal : dal; sc_rollup : sc_rollup; + zk_rollup : zk_rollup; } val encoding : t Data_encoding.t @@ -1006,6 +1009,10 @@ module Constants : sig val max_number_of_stored_cemented_commitments : context -> int + val zk_rollup_enable : context -> bool + + val zk_rollup_min_pending_to_process : context -> int + (** All constants: fixed and parametric *) type t = private {fixed : fixed; parametric : Parametric.t} @@ -2367,6 +2374,71 @@ module Bond_id : sig end end +module Zk_rollup : sig + module Address : S.HASH + + type t = Address.t + + type scalar := Bls12_381.Fr.t + + val to_scalar : t -> scalar + + module State : sig + type t = scalar array + + val encoding : t Data_encoding.t + end + + module Account : sig + module SMap : Map.S with type key = string + + type static = { + public_parameters : Plonk.public_parameters; + state_length : int; + circuits_info : bool SMap.t; + nb_ops : int; + } + + type dynamic = {state : State.t} + + type t = {static : static; dynamic : dynamic} + + val encoding : t Data_encoding.t + end + + module Operation : sig + type t = { + op_code : int; + price : Ticket_hash.t * Z.t; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Address.t; + payload : scalar array; + } + + val encoding : t Data_encoding.t + + val to_scalar_array : t -> scalar array + end + + type pending_list = + | Empty of {next_index : int64} + | Pending of {next_index : int64; length : int} + + val pending_list_encoding : pending_list Data_encoding.t + + val originate : + context -> + Account.static -> + init_state:State.t -> + (context * Address.t * Z.t) tzresult Lwt.t + + val exists : context -> t -> (context * bool) tzresult Lwt.t + + module Internal_for_tests : sig + val originated_zk_rollup : Origination_nonce.Internal_for_tests.t -> t + end +end + (** This module re-exports definitions from {!Receipt_repr}. *) module Receipt : sig type balance = @@ -3830,6 +3902,8 @@ module Kind : sig type sc_rollup_dal_slot_subscribe = Sc_rollup_dal_slot_subscribe_kind + type zk_rollup_origination = Zk_rollup_origination_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -3863,6 +3937,7 @@ module Kind : sig | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager end (** All the definitions below are re-exported from {!Operation_repr}. *) @@ -4100,6 +4175,13 @@ and _ manager_operation = slot_index : Dal.Slot_index.t; } -> Kind.sc_rollup_dal_slot_subscribe manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : bool Zk_rollup.Account.SMap.t; + init_state : Zk_rollup.State.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation and counter = Z.t @@ -4286,6 +4368,9 @@ module Operation : sig val sc_rollup_dal_slot_subscribe_case : Kind.sc_rollup_dal_slot_subscribe Kind.manager case + val zk_rollup_origination_case : + Kind.zk_rollup_origination Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -4353,6 +4438,8 @@ module Operation : sig val sc_rollup_dal_slot_subscribe_case : Kind.sc_rollup_dal_slot_subscribe case + + val zk_rollup_origination_case : Kind.zk_rollup_origination case end end @@ -4667,6 +4754,14 @@ module Fees : sig Z.t -> (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + val burn_zk_rollup_origination_fees : + ?origin:Receipt.update_origin -> + context -> + storage_limit:Z.t -> + payer:Token.source -> + Z.t -> + (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + type error += Cannot_pay_storage_fee (* `Temporary *) type error += Operation_quota_exceeded (* `Temporary *) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 03d7399fc9a8fddb40b098b7ee1d28cd61daf0e2..3374e097ab2e68e8288d224a3e58e55c9998ffbb 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1378,6 +1378,15 @@ let apply_manager_operation : Sc_rollup_dal_slot_subscribe_result {consumed_gas; slot_index; level} in (ctxt, result, []) + | Zk_rollup_origination {public_parameters; circuits_info; init_state; nb_ops} + -> + Zk_rollup_apply.originate + ~ctxt_before_op + ~ctxt + ~public_parameters + ~circuits_info + ~init_state + ~nb_ops type success_or_failure = Success of context | Failure @@ -1598,6 +1607,17 @@ let burn_manager_storage_fees : ) | Sc_rollup_recover_bond_result _ -> return (ctxt, storage_limit, smopr) | Sc_rollup_dal_slot_subscribe_result _ -> return (ctxt, storage_limit, smopr) + | Zk_rollup_origination_result payload -> + Fees.burn_zk_rollup_origination_fees + ctxt + ~storage_limit + ~payer + payload.size + >>=? fun (ctxt, storage_limit, balance_updates) -> + let result = + Zk_rollup_origination_result {payload with balance_updates} + in + return (ctxt, storage_limit, result) (** [burn_internal_storage_fees ctxt smopr storage_limit payer] burns the storage fees associated to an internal operation result [smopr]. diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index 153bcaf99e9dc33934b356c52837b769eef88137..a7c62eba5632943fc5521283e3ec6037bcf1e270 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -176,6 +176,13 @@ type _ successful_manager_operation_result = level : Raw_level.t; } -> Kind.sc_rollup_dal_slot_subscribe successful_manager_operation_result + | Zk_rollup_origination_result : { + balance_updates : Receipt.balance_updates; + originated_zk_rollup : Zk_rollup.t; + consumed_gas : Gas.Arith.fp; + size : Z.t; + } + -> Kind.zk_rollup_origination successful_manager_operation_result let migration_origination_result_to_successful_manager_operation_result ({ @@ -741,6 +748,45 @@ module Manager_result = struct ~kind:Kind.Dal_publish_slot_header_manager_kind ~inj:(fun consumed_gas -> Dal_publish_slot_header_result {consumed_gas}) + let zk_rollup_origination_case = + make + ~op_case:Operation.Encoding.Manager_operations.zk_rollup_origination_case + ~encoding: + Data_encoding.( + obj5 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "originated_zk_rollup" Zk_rollup.Address.encoding) + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "size" z)) + ~select:(function + | Successful_manager_result (Zk_rollup_origination_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Zk_rollup_origination_manager_kind + ~proj:(function + | Zk_rollup_origination_result + {balance_updates; originated_zk_rollup; consumed_gas; size} -> + ( balance_updates, + originated_zk_rollup, + Gas.Arith.ceil consumed_gas, + consumed_gas, + size )) + ~inj: + (fun ( balance_updates, + originated_zk_rollup, + consumed_gas, + consumed_milligas, + size ) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + Zk_rollup_origination_result + { + balance_updates; + originated_zk_rollup; + consumed_gas = consumed_milligas; + size; + }) + let sc_rollup_originate_case = make ~op_case:Operation.Encoding.Manager_operations.sc_rollup_originate_case @@ -1129,6 +1175,10 @@ let equal_manager_kind : Kind.Sc_rollup_dal_slot_subscribe_manager_kind ) -> Some Eq | Kind.Sc_rollup_dal_slot_subscribe_manager_kind, _ -> None + | ( Kind.Zk_rollup_origination_manager_kind, + Kind.Zk_rollup_origination_manager_kind ) -> + Some Eq + | Kind.Zk_rollup_origination_manager_kind, _ -> None module Encoding = struct type 'kind case = @@ -1743,6 +1793,17 @@ module Encoding = struct res ) -> Some (op, res) | _ -> None) + + let zk_rollup_origination_case = + make_manager_case + Operation.Encoding.zk_rollup_origination_case + Manager_result.zk_rollup_origination_case + (function + | Contents_and_result + ( (Manager_operation {operation = Zk_rollup_origination _; _} as op), + res ) -> + Some (op, res) + | _ -> None) end let contents_result_encoding = @@ -1801,6 +1862,7 @@ let contents_result_encoding = make sc_rollup_execute_outbox_message_case; make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; + make zk_rollup_origination_case; ] let contents_and_result_encoding = @@ -1864,6 +1926,7 @@ let contents_and_result_encoding = make sc_rollup_execute_outbox_message_case; make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; + make zk_rollup_origination_case; ] type 'kind contents_result_list = @@ -2691,6 +2754,32 @@ let kind_equal : } ) -> Some Eq | Manager_operation {operation = Sc_rollup_dal_slot_subscribe _; _}, _ -> None + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + {operation_result = Applied (Zk_rollup_origination_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + {operation_result = Backtracked (Zk_rollup_origination_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Zk_rollup_origination_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Zk_rollup_origination_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Zk_rollup_origination _; _}, _ -> None let rec kind_equal_list : type kind kind2. diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 737894532feffc53ea6d65be0c902aed6e92422a..9b70c8eb0166c6ac877c6bb86072a2b9813e838f 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -272,6 +272,13 @@ and _ successful_manager_operation_result = level : Raw_level.t; } -> Kind.sc_rollup_dal_slot_subscribe successful_manager_operation_result + | Zk_rollup_origination_result : { + balance_updates : Receipt.balance_updates; + originated_zk_rollup : Zk_rollup.t; + consumed_gas : Gas.Arith.fp; + size : Z.t; + } + -> Kind.zk_rollup_origination successful_manager_operation_result and packed_successful_manager_operation_result = | Successful_manager_result : diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index 2244d5bb9dbcc7aa842eb2fb323098fdc618cd19..d5744558b6d4ce733734a36d1cf52e4fbcd8876f 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -127,6 +127,8 @@ type sc_rollup = { max_number_of_stored_cemented_commitments : int; } +type zk_rollup = {enable : bool; min_pending_to_process : int} + type t = { preserved_cycles : int; blocks_per_cycle : int32; @@ -172,6 +174,7 @@ type t = { tx_rollup : tx_rollup; dal : dal; sc_rollup : sc_rollup; + zk_rollup : zk_rollup; } let tx_rollup_encoding = @@ -305,6 +308,20 @@ let sc_rollup_encoding = (req "sc_rollup_timeout_period_in_blocks" int31) (req "sc_rollup_max_number_of_cemented_commitments" int31))) +let zk_rollup_encoding = + let open Data_encoding in + conv + (fun ({enable; min_pending_to_process} : zk_rollup) -> + (enable, min_pending_to_process)) + (fun (zk_rollup_enable, zk_rollup_min_pending_to_process) -> + { + enable = zk_rollup_enable; + min_pending_to_process = zk_rollup_min_pending_to_process; + }) + (obj2 + (req "zk_rollup_enable" bool) + (req "zk_rollup_min_pending_to_process" int31)) + let encoding = let open Data_encoding in conv @@ -348,7 +365,7 @@ let encoding = ( ( c.cache_script_size, c.cache_stake_distribution_cycles, c.cache_sampler_state_cycles ), - (c.tx_rollup, (c.dal, c.sc_rollup)) ) ) ) ) )) + (c.tx_rollup, (c.dal, (c.sc_rollup, c.zk_rollup))) ) ) ) ) )) (fun ( ( preserved_cycles, blocks_per_cycle, blocks_per_commitment, @@ -388,7 +405,7 @@ let encoding = ( ( cache_script_size, cache_stake_distribution_cycles, cache_sampler_state_cycles ), - (tx_rollup, (dal, sc_rollup)) ) ) ) ) ) -> + (tx_rollup, (dal, (sc_rollup, zk_rollup))) ) ) ) ) ) -> { preserved_cycles; blocks_per_cycle; @@ -432,6 +449,7 @@ let encoding = tx_rollup; dal; sc_rollup; + zk_rollup; }) (merge_objs (obj10 @@ -492,4 +510,4 @@ let encoding = tx_rollup_encoding (merge_objs (obj1 (req "dal_parametric" dal_encoding)) - sc_rollup_encoding))))))) + (merge_objs sc_rollup_encoding zk_rollup_encoding)))))))) diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index 52196fa7196697efde7ecabae8ba4563a5f1bd10..7c0de926e5517111b79acd0e3e82ab997e96afd7 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -126,6 +126,17 @@ type sc_rollup = { max_number_of_stored_cemented_commitments : int; } +type zk_rollup = { + enable : bool; + (* Minimum number of pending operations that can be processed by a ZKRU + update, if available. + If the length of the pending list is less than [min_pending_to_process], + then an update needs to process all pending operations to be valid. + That is, every update must process at least + [min(length pending_list, min_pending_to_process)] pending operations. *) + min_pending_to_process : int; +} + type t = { preserved_cycles : int; blocks_per_cycle : int32; @@ -177,6 +188,7 @@ type t = { tx_rollup : tx_rollup; dal : dal; sc_rollup : sc_rollup; + zk_rollup : zk_rollup; } val encoding : t Data_encoding.encoding diff --git a/src/proto_alpha/lib_protocol/constants_storage.ml b/src/proto_alpha/lib_protocol/constants_storage.ml index 22f603cb6630c8cdd23743fee0fed13431c2ec18..45b2c3dfa0ce3b3c766fd4bb8fdbfa33c51d22a5 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.ml +++ b/src/proto_alpha/lib_protocol/constants_storage.ml @@ -281,3 +281,11 @@ let dal_number_of_slots c = let dal_enable c = let constants = Raw_context.constants c in constants.dal.feature_enable + +let zk_rollup_enable c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.enable + +let zk_rollup_min_pending_to_process c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.min_pending_to_process diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index 0169e9299a4b6a9bdfa7d588d84dc1e6f2ebbcde..c454dcb39767899d2590941905072dd35fc710ca 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -163,3 +163,7 @@ val sc_rollup_timeout_period_in_blocks : Raw_context.t -> int val dal_number_of_slots : Raw_context.t -> int val dal_enable : Raw_context.t -> bool + +val zk_rollup_enable : Raw_context.t -> bool + +val zk_rollup_min_pending_to_process : Raw_context.t -> int diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 1ca2458363a80dfe406f1bdc436d14cee7c99a82..9275c35df69ec83beca8c8c5c5bf615ab145984f 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -107,6 +107,11 @@ Dal_slot_repr Dal_endorsement_repr Dal_errors_repr + Zk_rollup_scalar + Zk_rollup_repr + Zk_rollup_state_repr + Zk_rollup_account_repr + Zk_rollup_operation_repr Bond_id_repr Vote_repr Liquidity_baking_repr @@ -143,6 +148,7 @@ Commitment_storage Voting_period_storage Cache_repr + Zk_rollup_storage Contract_delegate_storage Stake_storage Contract_storage @@ -226,6 +232,7 @@ Sc_rollup_management_protocol Sc_rollup_operations Dal_apply + Zk_rollup_apply Baking Validate_errors Amendment @@ -353,6 +360,11 @@ dal_slot_repr.ml dal_slot_repr.mli dal_endorsement_repr.ml dal_endorsement_repr.mli dal_errors_repr.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli liquidity_baking_repr.ml liquidity_baking_repr.mli @@ -389,6 +401,7 @@ commitment_storage.ml commitment_storage.mli voting_period_storage.ml voting_period_storage.mli cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli contract_delegate_storage.ml contract_delegate_storage.mli stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli @@ -472,6 +485,7 @@ sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli sc_rollup_operations.ml sc_rollup_operations.mli dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli baking.ml baking.mli validate_errors.ml validate_errors.mli amendment.ml amendment.mli @@ -579,6 +593,11 @@ dal_slot_repr.ml dal_slot_repr.mli dal_endorsement_repr.ml dal_endorsement_repr.mli dal_errors_repr.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli liquidity_baking_repr.ml liquidity_baking_repr.mli @@ -615,6 +634,7 @@ commitment_storage.ml commitment_storage.mli voting_period_storage.ml voting_period_storage.mli cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli contract_delegate_storage.ml contract_delegate_storage.mli stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli @@ -698,6 +718,7 @@ sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli sc_rollup_operations.ml sc_rollup_operations.mli dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli baking.ml baking.mli validate_errors.ml validate_errors.mli amendment.ml amendment.mli @@ -810,6 +831,11 @@ dal_slot_repr.ml dal_slot_repr.mli dal_endorsement_repr.ml dal_endorsement_repr.mli dal_errors_repr.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli liquidity_baking_repr.ml liquidity_baking_repr.mli @@ -846,6 +872,7 @@ commitment_storage.ml commitment_storage.mli voting_period_storage.ml voting_period_storage.mli cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli contract_delegate_storage.ml contract_delegate_storage.mli stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli @@ -929,6 +956,7 @@ sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli sc_rollup_operations.ml sc_rollup_operations.mli dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli baking.ml baking.mli validate_errors.ml validate_errors.mli amendment.ml amendment.mli diff --git a/src/proto_alpha/lib_protocol/fees_storage.ml b/src/proto_alpha/lib_protocol/fees_storage.ml index 134b46d1470ec18adcb91949b4087b3ed2102332..364ba8d59ab0bdab4a784ea5d61bfaa4544239df 100644 --- a/src/proto_alpha/lib_protocol/fees_storage.ml +++ b/src/proto_alpha/lib_protocol/fees_storage.ml @@ -145,6 +145,10 @@ let burn_sc_rollup_origination_fees ?(origin = Receipt_repr.Block_application) c ~storage_limit ~payer consumed = burn_storage_fees ~origin c ~storage_limit ~payer consumed +let burn_zk_rollup_origination_fees ?(origin = Receipt_repr.Block_application) c + ~storage_limit ~payer consumed = + burn_storage_fees ~origin c ~storage_limit ~payer consumed + let check_storage_limit c ~storage_limit = if Compare.Z.( diff --git a/src/proto_alpha/lib_protocol/fees_storage.mli b/src/proto_alpha/lib_protocol/fees_storage.mli index 3086687b83c391254273dbf578383b12e3f8a8b6..e66babbd7f9f5beb3e51e4c91275dd80e6fd7e4d 100644 --- a/src/proto_alpha/lib_protocol/fees_storage.mli +++ b/src/proto_alpha/lib_protocol/fees_storage.mli @@ -113,3 +113,13 @@ val burn_sc_rollup_origination_fees : payer:Token.source -> Z.t -> (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [burn_zk_rollup_origination_fees ~origin ctxt ~storage_limit ~payer consumed] + burns the storage fees for ZK rollup origination fees. *) +val burn_zk_rollup_origination_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + storage_limit:Z.t -> + payer:Token.source -> + Z.t -> + (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 5fcefe0170e9e7677360c34fed80bc7f57e3070a..d68a6f95e893b34c2a06589cdafae995ddbcbda0 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -119,6 +119,8 @@ module Kind = struct type sc_rollup_dal_slot_subscribe = Sc_rollup_dal_slot_subscribe_kind + type zk_rollup_origination = Zk_rollup_origination_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -152,6 +154,7 @@ module Kind = struct | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager end type 'a consensus_operation_type = @@ -457,6 +460,13 @@ and _ manager_operation = slot_index : Dal_slot_repr.Index.t; } -> Kind.sc_rollup_dal_slot_subscribe manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : bool Zk_rollup_account_repr.SMap.t; + init_state : Zk_rollup_state_repr.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation and counter = Z.t @@ -492,6 +502,7 @@ let manager_kind : type kind. kind manager_operation -> kind Kind.manager = | Sc_rollup_recover_bond _ -> Kind.Sc_rollup_recover_bond_manager_kind | Sc_rollup_dal_slot_subscribe _ -> Kind.Sc_rollup_dal_slot_subscribe_manager_kind + | Zk_rollup_origination _ -> Kind.Zk_rollup_origination_manager_kind type packed_manager_operation = | Manager : 'kind manager_operation -> packed_manager_operation @@ -590,6 +601,10 @@ let dal_offset = 230 let dal_publish_slot_header_tag = dal_offset + 0 +let zk_rollup_operation_tag_offset = 250 + +let zk_rollup_operation_create_tag = zk_rollup_operation_tag_offset + 0 + module Encoding = struct open Data_encoding @@ -1007,6 +1022,52 @@ module Encoding = struct {contents; ty; ticketer; amount; destination; entrypoint}); } + let zk_rollup_origination_case = + MCase + { + tag = zk_rollup_operation_create_tag; + name = "zk_rollup_origination"; + encoding = + obj4 + (req "public_parameters" Plonk.public_parameters_encoding) + (let circuits_info_encoding = + conv_with_guard + (fun m -> + List.of_seq @@ Zk_rollup_account_repr.SMap.to_seq m) + (fun l -> + let m = + Zk_rollup_account_repr.SMap.of_seq @@ List.to_seq l + in + if + (* Check that the list has no duplicated keys *) + Compare.List_length_with.( + l <> Zk_rollup_account_repr.SMap.cardinal m) + then + Error + "Zk_rollup_origination: circuits_info has duplicated \ + keys" + else Ok m) + (list (tup2 string bool)) + in + req "circuits_info" circuits_info_encoding) + (req "init_state" Zk_rollup_state_repr.encoding) + (* TODO https://gitlab.com/tezos/tezos/-/issues/3655 + Encoding of non-negative [nb_ops] for origination *) + (req "nb_ops" int31); + select = + (function + | Manager (Zk_rollup_origination _ as op) -> Some op | _ -> None); + proj = + (function + | Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops} -> + (public_parameters, circuits_info, init_state, nb_ops)); + inj = + (fun (public_parameters, circuits_info, init_state, nb_ops) -> + Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops}); + } + let sc_rollup_originate_case = MCase { @@ -1628,6 +1689,11 @@ module Encoding = struct sc_rollup_operation_dal_slot_subscribe_tag Manager_operations.sc_rollup_dal_slot_subscribe_case + let zk_rollup_origination_case = + make_manager_case + zk_rollup_operation_create_tag + Manager_operations.zk_rollup_origination_case + let contents_encoding = let make (Case {tag; name; encoding; select; proj; inj}) = case @@ -1678,6 +1744,7 @@ module Encoding = struct make sc_rollup_execute_outbox_message_case; make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; + make zk_rollup_origination_case; ] let contents_list_encoding = @@ -1912,6 +1979,8 @@ let equal_manager_operation_kind : | Sc_rollup_recover_bond _, _ -> None | Sc_rollup_dal_slot_subscribe _, Sc_rollup_dal_slot_subscribe _ -> Some Eq | Sc_rollup_dal_slot_subscribe _, _ -> None + | Zk_rollup_origination _, Zk_rollup_origination _ -> Some Eq + | Zk_rollup_origination _, _ -> None let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option = diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 155fe27b0c0b33e9dd5a82eae671d122eb9c0d02..5131ca50357ac445a184a12dbf135536d57f4618 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -49,6 +49,7 @@ - tx rollup withdraw - tx rollup reveal withdrawals - smart contract rollup origination + - zk rollup origination Each of them can be encoded as raw bytes. Operations are distinguished at type level using phantom type parameters. [packed_operation] type allows @@ -148,6 +149,8 @@ module Kind : sig type sc_rollup_dal_slot_subscribe = Sc_rollup_dal_slot_subscribe_kind + type zk_rollup_origination = Zk_rollup_origination_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -181,6 +184,7 @@ module Kind : sig | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager end type 'a consensus_operation_type = @@ -540,6 +544,15 @@ and _ manager_operation = slot_index : Dal_slot_repr.Index.t; } -> Kind.sc_rollup_dal_slot_subscribe manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : bool Zk_rollup_account_repr.SMap.t; + (** Circuit names, alongside a boolean flag indicating + if they can be used for private ops. *) + init_state : Zk_rollup_state_repr.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation (** Counters are used as anti-replay protection mechanism in manager operations: each manager account stores a counter and @@ -703,6 +716,8 @@ module Encoding : sig val sc_rollup_dal_slot_subscribe_case : Kind.sc_rollup_dal_slot_subscribe Kind.manager case + val zk_rollup_origination_case : Kind.zk_rollup_origination Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -769,5 +784,7 @@ module Encoding : sig val sc_rollup_dal_slot_subscribe_case : Kind.sc_rollup_dal_slot_subscribe case + + val zk_rollup_origination_case : Kind.zk_rollup_origination case end end diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index f54908042025d5558596df02b4bca0e503807cef..794101fd9535b9e3da4bfedf81e7b275a3a60b26 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -302,6 +302,8 @@ let[@inline] tx_rollup ctxt = ctxt.back.constants.tx_rollup let[@inline] sc_rollup ctxt = ctxt.back.constants.sc_rollup +let[@inline] zk_rollup ctxt = ctxt.back.constants.zk_rollup + let[@inline] recover ctxt = ctxt.back.context let[@inline] fees ctxt = ctxt.back.fees @@ -990,6 +992,9 @@ let prepare_first_block ~level ~timestamp ctxt = max_number_of_stored_cemented_commitments = 5; } in + let zk_rollup = + Constants_parametric_repr.{enable = false; min_pending_to_process = 10} + in let constants = Constants_parametric_repr. { @@ -1039,6 +1044,7 @@ let prepare_first_block ~level ~timestamp ctxt = tx_rollup; dal; sc_rollup; + zk_rollup; } in add_constants ctxt constants >>= fun ctxt -> return ctxt) diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index 0f612ebe7a7d8ef850aa22393c2d0217230d5337..feec6955288d30a967fbf81c199ced4444e29c25 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -109,6 +109,8 @@ val tx_rollup : t -> Constants_parametric_repr.tx_rollup val sc_rollup : t -> Constants_parametric_repr.sc_rollup +val zk_rollup : t -> Constants_parametric_repr.zk_rollup + val patch_constants : t -> (Constants_parametric_repr.t -> Constants_parametric_repr.t) -> t Lwt.t diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index cc3787c1f20fc7492fe01687086ce08c98617aa9..cdd6ee9b6fd760575b57e2effc669b94e4b3a354 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1897,3 +1897,89 @@ module Dal = struct let encoding = Data_encoding.(list Dal_slot_repr.encoding) end) end + +module Zk_rollup = struct + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["zk_rollup"] + end)) + (Make_index (Zk_rollup_repr.Index)) + + module Account : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_account_repr.t = + Indexed_context.Make_carbonated_map + (struct + let name = ["account"] + end) + (Zk_rollup_account_repr) + + module Pending_list = + Indexed_context.Make_carbonated_map + (struct + let name = ["pending_list"] + end) + (struct + type t = Zk_rollup_repr.pending_list + + let encoding = Zk_rollup_repr.pending_list_encoding + end) + + module Pending_operation : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * Zk_rollup_repr.t + and type key = int64 + and type value = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["pending_operations"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + Int64.of_string_opt hash + |> Result.of_option + ~error:"Cannot parse pending operation position" + in + RPC_arg.make + ~descr: + "The position of an operation in a pending operations list" + ~name:"zkru_pending_op_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "zkru_pending_op_position" + ~title:"Zkru pending operation position" + ~description: + "The position of an operation in a pending operations list" + Data_encoding.Compact.(make ~tag_size:`Uint8 int64) + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (struct + type t = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option + + let encoding = + Data_encoding.( + tup2 + Zk_rollup_operation_repr.encoding + (option Ticket_hash_repr.encoding)) + end) +end diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 8eaeecaee429fb23c68f397080ab1d0f06a82e4d..590988c668affbd38dc07404887646508c63959b 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -875,3 +875,33 @@ module Dal : sig and type key = Raw_level_repr.t and type value = Dal_slot_repr.slot list end + +module Zk_rollup : sig + (** Zero ZK rollup. + + Each ZK rollup is associated to: + + - an Account, as described in [Zk_rollup_repr] + - a pending list description, consisting of its head's index and + a counter + - a map from integer indeces to L2 operations, to store the actual + pending list + *) + module Account : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_account_repr.t + + module Pending_list : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_repr.pending_list + + module Pending_operation : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * Zk_rollup_repr.t + and type key = int64 + and type value = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option +end diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 53f70e3a3f424dcb08e6a69e60d508798744d749..9e41417caef8cb2e3862d105edcaffecc9fac123 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -446,7 +446,8 @@ let prepare_initial_context_params ?consensus_threshold ?min_proposal_quorum ?blocks_per_cycle ?cycles_per_voting_period ?tx_rollup_enable ?tx_rollup_sunset_level ?tx_rollup_origination_size ?sc_rollup_enable ?sc_rollup_max_number_of_messages_per_commitment_period ?dal_enable - ?hard_gas_limit_per_block ?nonce_revelation_threshold initial_accounts = + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold + initial_accounts = let open Tezos_protocol_alpha_parameters in let constants = Default_parameters.constants_test in let min_proposal_quorum = @@ -513,6 +514,9 @@ let prepare_initial_context_params ?consensus_threshold ?min_proposal_quorum let dal_enable = Option.value ~default:constants.dal.feature_enable dal_enable in + let zk_rollup_enable = + Option.value ~default:constants.zk_rollup.enable zk_rollup_enable + in let hard_gas_limit_per_block = Option.value ~default:constants.hard_gas_limit_per_block @@ -551,6 +555,7 @@ let prepare_initial_context_params ?consensus_threshold ?min_proposal_quorum sc_rollup_max_number_of_messages_per_commitment_period; }; dal = {constants.dal with feature_enable = dal_enable}; + zk_rollup = {constants.zk_rollup with enable = zk_rollup_enable}; hard_gas_limit_per_block; nonce_revelation_threshold; } @@ -604,7 +609,7 @@ let genesis ?commitments ?consensus_threshold ?min_proposal_quorum ?cycles_per_voting_period ?tx_rollup_enable ?tx_rollup_sunset_level ?tx_rollup_origination_size ?sc_rollup_enable ?sc_rollup_max_number_of_messages_per_commitment_period ?dal_enable - ?hard_gas_limit_per_block ?nonce_revelation_threshold + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold (initial_accounts : (Account.t * Tez.t * Signature.Public_key_hash.t option) list) = prepare_initial_context_params @@ -625,6 +630,7 @@ let genesis ?commitments ?consensus_threshold ?min_proposal_quorum ?sc_rollup_enable ?sc_rollup_max_number_of_messages_per_commitment_period ?dal_enable + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold initial_accounts @@ -818,7 +824,8 @@ let bake_n_with_all_balance_updates ?(baking_mode = Application) ?policy | Sc_rollup_timeout_result _ | Sc_rollup_execute_outbox_message_result _ | Sc_rollup_recover_bond_result _ - | Sc_rollup_dal_slot_subscribe_result _ -> + | Sc_rollup_dal_slot_subscribe_result _ + | Zk_rollup_origination_result _ -> balance_updates_rev | Transaction_result ( Transaction_to_contract_result {balance_updates; _} @@ -870,7 +877,7 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = (Sc_rollup_execute_outbox_message_result _) | Successful_manager_result (Sc_rollup_recover_bond_result _) | Successful_manager_result (Sc_rollup_dal_slot_subscribe_result _) - -> + | Successful_manager_result (Zk_rollup_origination_result _) -> origination_results_rev | Successful_manager_result (Origination_result x) -> Origination_result x :: origination_results_rev) diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index ce57cd710fba101fed451684c63ea1e9c08adf2d..286b91ff5f2d3c39fb650a27997224d0e37d8638 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -130,6 +130,7 @@ val genesis : ?sc_rollup_enable:bool -> ?sc_rollup_max_number_of_messages_per_commitment_period:int -> ?dal_enable:bool -> + ?zk_rollup_enable:bool -> ?hard_gas_limit_per_block:Gas.Arith.integral -> ?nonce_revelation_threshold:int32 -> (Account.t * Tez.tez * Signature.Public_key_hash.t option) list -> @@ -275,6 +276,7 @@ val prepare_initial_context_params : ?sc_rollup_enable:bool -> ?sc_rollup_max_number_of_messages_per_commitment_period:int -> ?dal_enable:bool -> + ?zk_rollup_enable:bool -> ?hard_gas_limit_per_block:Gas.Arith.integral -> ?nonce_revelation_threshold:int32 -> (Account.t * Tez.t * Signature.Public_key_hash.t option) list -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index 53959305ccefd668dc4f9f597ffca295e994aec0..aecb15ac3237a4b2c9a36199e6801632819ad44e 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -460,7 +460,7 @@ let init_gen tup ?rng_state ?commitments ?(initial_balances = []) ?cycles_per_voting_period ?tx_rollup_enable ?tx_rollup_sunset_level ?tx_rollup_origination_size ?sc_rollup_enable ?sc_rollup_max_number_of_messages_per_commitment_period ?dal_enable - ?hard_gas_limit_per_block ?nonce_revelation_threshold () = + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold () = let n = tup_n tup in let accounts = Account.generate_accounts @@ -494,6 +494,7 @@ let init_gen tup ?rng_state ?commitments ?(initial_balances = []) ?sc_rollup_enable ?sc_rollup_max_number_of_messages_per_commitment_period ?dal_enable + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold accounts diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 07536aa7bfe5ee94936c6549ccf036c63b20cf85..68506b9f04efb6aa2a65f8f5fcaeeb841d97dbc5 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -284,6 +284,7 @@ type 'accounts init := ?sc_rollup_enable:bool -> ?sc_rollup_max_number_of_messages_per_commitment_period:int -> ?dal_enable:bool -> + ?zk_rollup_enable:bool -> ?hard_gas_limit_per_block:Gas.Arith.integral -> ?nonce_revelation_threshold:int32 -> unit -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml b/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml new file mode 100644 index 0000000000000000000000000000000000000000..b961f894b1286121212e2104d85416f1e302d7f3 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml @@ -0,0 +1,466 @@ +(*****************************************************************************) +(* *) +(* MIT License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Dummy ZK Rollup for testing the ZKRU integration in the protocol. + The library Plompiler is used to build the circuits (in a module V as + verifier) and the corresponding functions to produce the inputs for the + circuits (in a module P as prover). + + The state of this rollup is a boolean value, which will be + represented with a scalar value of [zero] for [false] and + [one] for [true]. + + This RU has only one operation, with [op_code] 0. In addition to the + common header (see {!Zk_rollup_operation_repr}), this operation has + as payload one scalar representing a boolean value. + + The transition function [f] for this rollup is: + + {[ + f : operation -> state -> state + f (Op b) s = if b = s then not s else s + ]} + + That is, the state bool is flipped only if the operation's payload is + equal to the current state. + + The operation can be used publicly or in a private batch. The circuits + that describe the RU are: + - ["op"]: for a single public operation. + - ["batch-"[N]]: for a batch of [N] private operations. [N] is determined + by the [batch_size] parameter to the [Operator] functor. + - ["fee"]: the trivial fees circuit, since this RU has no concept of fees. + + NB: the "op" circuit does not add any constraints over the operation's + [exit_validity] other than it being in {0, 1}. This means that the dummy + rollup can be used to test deposits/withdrawals, but the rollup will not + perform any monetary bookkeeping. +*) + +open Plompiler + +(** Helper types and modules *) + +(** Empty types to represent bounds *) + +type balance + +type amount + +type fee + +type op_code + +(** Bounds required for the dummy rollup. *) +module Bound : sig + type 'a t = private Z.t + + val max_balance : balance t + + val max_amount : amount t + + val max_fee : fee t + + val max_op_code : op_code t + + val v : 'a t -> Z.t +end = struct + type 'a t = Z.t + + (** Maximum ticket balance, as found in the price field of an operation's + header *) + let max_balance = Z.(shift_left one 20) + + (** Maximum ticket amount, used for fee circuit *) + let max_amount = Z.(shift_left one 20) + + (** Maximum fee amount for one public operation *) + let max_fee = Z.(shift_left one 10) + + (** Maximum value for op code *) + let max_op_code = Z.(shift_left one 1) + + let v x = x +end + +(** Modules to manipulate bounded integers, both as OCaml values and in circuit + representation. +*) +module Bounded = Bounded.Make (Bound) + +(** Types used for the Dummy Rollup circuits. + This module is split into: + - P: concrete OCaml version of the types, + - V: Plompiler's circuit representation for P's types, and + - Encodings: conversion between P and V. +*) +module Types = struct + module P = struct + type state = bool + + module Bounded = Bounded.P + + type 'a ticket = {id : S.t; amount : 'a Bounded.t} + + type tezos_pkh = Environment.Signature.Public_key_hash.t + + type header = { + op_code : op_code Bounded.t; + price : balance ticket; + l1_dst : tezos_pkh; + rollup_id : tezos_pkh; + } + + type op = {header : header; payload : bool} + + (** Dummy values for these types. Useful to get the circuit without having + the actual inputs. *) + module Dummy = struct + let op_code = Bounded.make ~bound:Bound.max_op_code Z.zero + + let balance = Bounded.make ~bound:Bound.max_balance Z.zero + + let tezos_pkh = Environment.Signature.Public_key_hash.zero + + let ticket_balance = {id = S.zero; amount = balance} + + let header = + { + op_code; + price = ticket_balance; + l1_dst = tezos_pkh; + rollup_id = tezos_pkh; + } + end + end + + module V (L : LIB) = struct + open L + module Bounded_u = Bounded.V (L) + + type 'a ticket_u = {id : scalar repr; amount : 'a Bounded_u.t} + + type tezos_pkh_u = scalar repr + + type header_u = { + op_code : op_code Bounded_u.t; + price : balance ticket_u; + l1_dst : tezos_pkh_u; + rollup_id : tezos_pkh_u; + } + + type op_u = {header : header_u; payload : bool repr} + end + + module Encodings (L : LIB) = struct + module Bounded_e = Bounded.Encoding (L) + open P + + open V (L) + + open Encodings (L) + + let op_code_encoding ~safety = Bounded_e.encoding ~safety Bound.max_op_code + + let encoding_to_scalar e x = + let bs = Data_encoding.Binary.to_bytes_exn e x in + let z = Z.of_bits @@ Bytes.to_string bs in + Bls12_381.Fr.of_z z + + let encoding_of_scalar e x = + let z = Bls12_381.Fr.to_z x in + let bs = Bytes.of_string @@ Z.to_bits z in + Data_encoding.Binary.of_bytes_exn e bs + + let tezos_pkh_encoding : (tezos_pkh, tezos_pkh_u, _) encoding = + conv + (fun pkhu -> pkhu) + (fun w -> w) + (encoding_to_scalar Signature.Public_key_hash.encoding) + (encoding_of_scalar Signature.Public_key_hash.encoding) + scalar_encoding + + let amount_encoding ~safety = Bounded_e.encoding ~safety Bound.max_amount + + let fee_encoding ~safety = Bounded_e.encoding ~safety Bound.max_fee + + let ticket_encoding ~safety (bound : 'a Bound.t) : + ('a ticket, 'a ticket_u, _) encoding = + conv + (fun {id; amount} -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (fun ({id; amount} : 'a ticket) -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (obj2_encoding scalar_encoding (Bounded_e.encoding ~safety bound)) + + let ticket_balance_encoding ~safety = + ticket_encoding ~safety Bound.max_balance + + let header_encoding ~safety : (header, header_u, _) encoding = + conv + (fun {op_code; price; l1_dst; rollup_id} -> + (op_code, (price, (l1_dst, rollup_id)))) + (fun (op_code, (price, (l1_dst, rollup_id))) -> + {op_code; price; l1_dst; rollup_id}) + (fun ({op_code; price; l1_dst; rollup_id} : header) -> + (op_code, (price, (l1_dst, rollup_id)))) + (fun (op_code, (price, (l1_dst, rollup_id))) -> + {op_code; price; l1_dst; rollup_id}) + (obj4_encoding + (op_code_encoding ~safety) + (ticket_balance_encoding ~safety) + tezos_pkh_encoding + tezos_pkh_encoding) + + let op_encoding : (op, op_u, _) encoding = + conv + (fun {header; payload} -> (header, payload)) + (fun (header, payload) -> {header; payload}) + (fun ({header; payload} : op) -> (header, payload)) + (fun (header, payload) -> {header; payload}) + (obj2_encoding (header_encoding ~safety:NoCheck) bool_encoding) + end +end + +(** Plompiler circuits for the dummy rollup *) +module V (L : LIB) = struct + open L + module E = Types.Encodings (L) + module Encodings = Encodings (L) + open Encodings + + open Types.V (L) + + let coerce (type a) (x : a Bounded_u.t) = + fst (x : a Bounded_u.t :> scalar repr * Z.t) + + (** Common logic for the state transition function *) + let logic_op ~old_state ~rollup_id op = + ignore rollup_id ; + let* valid = equal old_state op.payload in + let* new_state = Bool.bnot old_state in + let* expected_new_state = Bool.ifthenelse valid new_state old_state in + Num.assert_eq_const (coerce op.header.op_code) S.zero + (* >* assert_equal rollup_id op.header.rollup_id *) + >* ret expected_new_state + + (** Circuit definition for one public operation *) + let predicate_op ?(public = true) ~old_state ~new_state ~fee ~exit_validity + ~rollup_id op = + let* old_state = input ~public:true @@ Input.bool old_state in + let* new_state = input ~public:true @@ Input.bool new_state in + let* _fee = + input ~public:true + @@ E.((fee_encoding ~safety:Bounded_e.Unsafe).input) fee + in + let* _exit_validity = input ~public:true @@ Input.bool exit_validity in + let* rollup_id = + input ~public:true @@ E.(tezos_pkh_encoding.input) rollup_id + in + let* op = input ~public @@ E.op_encoding.input op in + let op = E.op_encoding.decode op in + let* expected_new_state = logic_op ~old_state ~rollup_id op in + assert_equal expected_new_state new_state + + (** Circuit definition for a batch of private operations *) + let predicate_batch ~old_state ~new_state ~fees ~rollup_id ops = + let* old_state = input ~public:true @@ Input.bool old_state in + let* new_state = input ~public:true @@ Input.bool new_state in + let* _fees = + input ~public:true + @@ E.((amount_encoding ~safety:Bounded_e.Unsafe).input) fees + in + let* rollup_id = + input ~public:true @@ E.(tezos_pkh_encoding.input) rollup_id + in + let* ops = input @@ (Encodings.list_encoding E.op_encoding).input ops in + let ops = (Encodings.list_encoding E.op_encoding).decode ops in + let* computed_final_state = + foldM + (fun old_state op -> logic_op ~old_state ~rollup_id op) + old_state + ops + in + assert_equal computed_final_state new_state + + (** Fee circuit *) + let predicate_fees ~old_state ~new_state ~fees = + let* old_state = input ~public:true @@ Input.bool old_state in + let* new_state = input ~public:true @@ Input.bool new_state in + let* _fees = + input ~public:true + @@ E.((amount_encoding ~safety:Bounded_e.Unsafe).input) fees + in + assert_equal old_state new_state +end + +(** Basic rollup operator for generating Updates. *) +module Operator (Params : sig + val batch_size : int +end) : sig + open Protocol.Alpha_context + + (** Initial state of the rollup *) + val init_state : Zk_rollup.State.t + + (** Map associating every circuit identifier to a boolean representing + whether the circuit can be part of a private batch *) + val circuits : bool Plonk.Main_protocol.SMap.t + + (** Commitment to the circuits *) + val public_parameters : + Plonk.Main_protocol.verifier_public_parameters + * Plonk.Main_protocol.transcript + + module Internal_for_tests : sig + val true_op : Zk_rollup.Operation.t + + val false_op : Zk_rollup.Operation.t + + val pending : Zk_rollup.Operation.t list + + val private_ops : Zk_rollup.Operation.t list list + end +end = struct + open Protocol.Alpha_context + module SMap = Plonk.Main_protocol.SMap + module Dummy = Types.P.Dummy + module T = Types.P + module VC = V (LibCircuit) + + let srs = + let open Bls12_381_polynomial.Polynomial in + (Srs.generate_insecure 8 1, Srs.generate_insecure 1 1) + + let dummy_l1_dst = + Hex.to_bytes_exn (`Hex "0002298c03ed7d454a101eb7022bc95f7e5f41ac78") + + let dummy_rollup_id = + (* zkr1PxS4vgvBsf6XVHRSB7UJKcrTWee8Dp7Wx *) + Hex.to_bytes_exn (`Hex "c9a524d4db6514471775c380231afc10f2ef6ba3") + + let dummy_ticket_hash = + Hex.to_bytes_exn (`Hex (String.init (2 * 32) @@ Fun.const '0')) + + let _of_proto_state : Zk_rollup.State.t -> Types.P.state = + fun s -> Bls12_381.Fr.is_one s.(0) + + let to_proto_state : Types.P.state -> Zk_rollup.State.t = + fun s -> if s then [|Bls12_381.Fr.one|] else [|Bls12_381.Fr.zero|] + + let dummy_op = T.{header = Dummy.header; payload = false} + + let batch_name = "batch-" ^ string_of_int Params.batch_size + + (* Circuits that define the rollup, alongside their public input size and + solver *) + let circuit_map = + let get_circuit _name c = + let r = LibCircuit.get_cs ~optimize:true c in + let _initial, public_input_size = LibCircuit.get_inputs c in + ( Plonk.Circuit.to_plonk ~public_input_size r.cs, + public_input_size, + r.solver ) + in + SMap.of_list + @@ List.map + (fun (n, c) -> (n, get_circuit n c)) + [ + ( "op", + VC.predicate_op + ~old_state:false + ~new_state:true + ~fee:(T.Bounded.make ~bound:Bound.max_fee Z.zero) + ~exit_validity:false + ~rollup_id:Dummy.tezos_pkh + dummy_op ); + ( batch_name, + VC.predicate_batch + ~old_state:false + ~new_state:true + ~fees:(T.Bounded.make ~bound:Bound.max_amount Z.zero) + ~rollup_id:Dummy.tezos_pkh + (Stdlib.List.init Params.batch_size (Fun.const dummy_op)) ); + ( "fee", + VC.predicate_fees + ~old_state:false + ~new_state:false + ~fees:(T.Bounded.make ~bound:Bound.max_amount Z.zero) ); + ] + + let circuits = + SMap.(add "op" false @@ add batch_name true @@ add "fee" false empty) + + let public_parameters, _prover_pp = + let (ppp, vpp), t = + Plonk.Main_protocol.setup_multi_circuits + ~zero_knowledge:false + (SMap.map (fun (a, b, _) -> (a, b)) circuit_map) + ~srs + in + ((vpp, t), ppp) + + let _insert s x m = + match SMap.find_opt s m with + | None -> SMap.add s [x] m + | Some l -> SMap.add s (x :: l) m + + let init_state = to_proto_state false + + module Internal_for_tests = struct + let true_op = + Zk_rollup.Operation. + { + op_code = 0; + price = + (let ticket_hash = + Data_encoding.Binary.of_bytes_exn + Ticket_hash.encoding + dummy_ticket_hash + in + (ticket_hash, Z.zero)); + l1_dst = + Data_encoding.Binary.of_bytes_exn + Signature.Public_key_hash.encoding + dummy_l1_dst; + rollup_id = + Data_encoding.Binary.of_bytes_exn + Zk_rollup.Address.encoding + dummy_rollup_id; + payload = [|Bls12_381.Fr.one|]; + } + + let false_op = {true_op with payload = [|Bls12_381.Fr.zero|]} + + let pending = [false_op; true_op; true_op] + + let n_batches = 10 + + let private_ops = + Stdlib.List.init n_batches @@ Fun.const + @@ Stdlib.List.init Params.batch_size (fun i -> + if i mod 2 = 0 then false_op else true_op) + end +end diff --git a/src/proto_alpha/lib_protocol/test/helpers/dune b/src/proto_alpha/lib_protocol/test/helpers/dune index 5fa328d81a1cd8f4b9337929da57f35f0f4d166e..9fb6dd17a57cd77dec1615b82b8da19f0355397a 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dune +++ b/src/proto_alpha/lib_protocol/test/helpers/dune @@ -17,7 +17,8 @@ tezos-protocol-alpha.parameters tezos-protocol-environment tezos-protocol-plugin-alpha - tezos-shell-services) + tezos-shell-services + tezos-plompiler) (flags (:standard) -open Tezos_base.TzPervasives diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index c532be84db2add6dfb82de9370352c079ab14482..ed1b4bca3cf7f848150b45c86688c1b1bf4f9278 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -950,3 +950,26 @@ let dal_publish_slot_header ?force_reveal ?counter ?fee ?gas_limit >>=? fun to_sign_op -> Context.Contract.manager ctxt src >|=? fun account -> sign account.sk ctxt to_sign_op + +let originated_zk_rollup op = + let packed = Operation.hash_packed op in + let nonce = Origination_nonce.Internal_for_tests.initial packed in + Zk_rollup.Internal_for_tests.originated_zk_rollup nonce + +let zk_rollup_origination ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt (src : Contract.t) ~public_parameters ~circuits_info ~init_state + ~nb_ops = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops}) + >>=? fun to_sign_op -> + Context.Contract.manager ctxt src >|=? fun account -> + let op = sign account.sk ctxt to_sign_op in + originated_zk_rollup op |> fun addr -> (op, addr) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index 5c9661760ca624224b8bed9b23cc7e3ae14913f4..5cb7c6159d6338de6eeff6e6b2764f06d630d658 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -698,3 +698,21 @@ val dal_publish_slot_header : Contract.t -> Dal.Slot.t -> (packed_operation, tztrace) result Lwt.t + +(** [zk_rollup_origination ctxt source ~public_parameters ~circuits_info + ~init_state ~nb_ops] tries to originate a ZK Rollup. *) +val zk_rollup_origination : + ?force_reveal:bool -> + ?counter:Z.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:counter -> + Context.t -> + Contract.t -> + public_parameters: + Plonk.Main_protocol.verifier_public_parameters + * Plonk.Main_protocol.transcript -> + circuits_info:bool Zk_rollup.Account.SMap.t -> + init_state:Zk_rollup.State.t -> + nb_ops:int -> + (Operation.packed * Zk_rollup.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml new file mode 100644 index 0000000000000000000000000000000000000000..af6814716a1501b332455134b9dad51c64f05550 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml @@ -0,0 +1 @@ +module Dummy_zk_rollup = Dummy_zk_rollup diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/main.ml b/src/proto_alpha/lib_protocol/test/integration/operations/main.ml index 70dff7c9241e4970ddb1cdc58b7ae897d884b84e..afcec61e65e4a3e501b6d47c2d4ea69267bf815f 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/main.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/main.ml @@ -45,5 +45,6 @@ let () = ("tx rollup", Test_tx_rollup.tests); ("sc rollup", Test_sc_rollup.tests); ("sc rollup transfer", Test_sc_rollup_transfer.tests); + ("zk rollup", Test_zk_rollup.tests); ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_zk_rollup.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_zk_rollup.ml new file mode 100644 index 0000000000000000000000000000000000000000..77125bdc3b68c3b055d2441021875647cb01c231 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_zk_rollup.ml @@ -0,0 +1,235 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Rollup layer 1 logic + Invocation: dune exec \ + src/proto_alpha/lib_protocol/test/integration/operations/main.exe \ + -- test "^zk rollup$" + Subject: Test zk rollup +*) + +open Protocol +open Alpha_context +open Lwt_result_syntax + +exception Zk_rollup_test_error of string + +(* Number of operations in each private batch *) +let batch_size = 10 + +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +(* Operation with payload = 1 *) +let true_op l1_dst rollup_id = + Zk_rollup.Operation. + { + op_code = 0; + price = Operator.Internal_for_tests.true_op.price; + l1_dst; + rollup_id; + payload = [|Bls12_381.Fr.one|]; + } + +let of_plonk_smap s = + Zk_rollup.Account.SMap.of_seq @@ Plonk.Main_protocol.SMap.to_seq s + +(* Operation with payload = 0 *) +let false_op l1_dst rollup_id = + {(true_op l1_dst rollup_id) with payload = [|Bls12_381.Fr.zero|]} + +(** [check_proto_error_f f t] checks that the first error of [t] + satisfies the boolean function [f]. *) +let check_proto_error_f f t = + match t with + | Environment.Ecoproto_error e :: _ when f e -> + Assert.test_error_encodings e ; + return_unit + | _ -> failwith "Unexpected error: %a" Error_monad.pp_print_trace t + +(** [check_proto_error e t] checks that the first error of [t] + equals [e]. *) +let check_proto_error e t = check_proto_error_f (( = ) e) t + +(* Check that originating a ZKRU fails when the feature flag is disabled. *) +let test_disable_feature_flag () = + let* b, contract = + Context.init_with_constants1 + { + Context.default_test_constants with + zk_rollup = + {Context.default_test_constants.zk_rollup with enable = false}; + } + in + let* i = Incremental.begin_construction b in + let* op, _zk_rollup = + Op.zk_rollup_origination + (I i) + contract + ~public_parameters:Operator.public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* _i = + Incremental.add_operation + ~expect_failure: + (check_proto_error Validate_errors.Manager.Zk_rollup_feature_disabled) + i + op + in + return_unit + +(** [context_init n] initializes a context for testing in which the + [zk_rollup_enable] constant is set to true. It returns the created + context and [n] contracts. *) +let context_init = + Context.init_with_constants_n + { + Context.default_test_constants with + zk_rollup = {Context.default_test_constants.zk_rollup with enable = true}; + consensus_threshold = 0; + } + +(* Check that the expected origination fees are paid. *) +let test_origination_fees () = + let* ctxt, contracts = context_init 1 in + let contract = Stdlib.List.hd contracts in + let expected_size = + let init_account = + Zk_rollup.Account. + { + static = + { + public_parameters = Operator.public_parameters; + state_length = 1; + circuits_info = of_plonk_smap Operator.circuits; + nb_ops = 1; + }; + dynamic = {state = Operator.init_state}; + } + in + let init_pl = Zk_rollup.(Empty {next_index = 0L}) in + Zk_rollup.Address.size + + Data_encoding.Binary.length Zk_rollup.Account.encoding init_account + + Data_encoding.Binary.length Zk_rollup.pending_list_encoding init_pl + in + let* constants = Context.get_constants (B ctxt) in + let expected_fees = + Tez.mul_exn constants.parametric.cost_per_byte expected_size + in + let* operation, _rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters:Operator.public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* balance_before = Context.Contract.balance (B ctxt) contract in + let* i = Incremental.begin_construction ctxt in + let* i = Incremental.add_operation i operation in + Assert.balance_was_debited + ~loc:__LOC__ + (I i) + contract + balance_before + expected_fees + +let test_origination_negative_nb_ops () = + let* ctxt, contracts = context_init 1 in + let contract = Stdlib.List.hd contracts in + let* operation, _rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters:Operator.public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:(-1) + in + let* i = Incremental.begin_construction ctxt in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup_apply.Zk_rollup_negative_nb_ops) + i + operation + in + return_unit + +(** Initializes the context and originates a ZKRU. *) +let init_and_originate n = + let* ctxt, contracts = context_init n in + let contract = Stdlib.List.hd contracts in + let* operation, rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters:Operator.public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* b = Block.bake ~operation ctxt in + return (b, contracts, rollup) + +let no_ticket op = (op, None) + +(* Checks that originating two ZK rollups leads to different + rollup addresses. *) +let test_originate_two_rollups () = + let* ctxt, contracts, zk_rollup1 = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let* operation, zk_rollup2 = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters:Operator.public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* _b = Block.bake ~operation ctxt in + assert (zk_rollup1 <> zk_rollup2) ; + return_unit + +let tests = + [ + Tztest.tztest + "check feature flag is disabled" + `Quick + test_disable_feature_flag; + Tztest.tztest "origination fees" `Quick test_origination_fees; + Tztest.tztest "originate two rollups" `Quick test_originate_two_rollups; + Tztest.tztest + "origination negative nb_ops" + `Quick + test_origination_negative_nb_ops; + ] diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml b/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml index dd40f8c10039719726fa31e63a3c2592ca785ec0..08f8d5ae24ecd4113036ad78212ba254a595b1b2 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml @@ -83,6 +83,7 @@ type ctxt_cstrs = { del_cstrs : cstrs; tx_cstrs : cstrs; sc_cstrs : cstrs; + zk_cstrs : cstrs; } (** {2 Default values} *) @@ -113,6 +114,7 @@ let default_ctxt_cstrs = del_cstrs = default_cstrs; tx_cstrs = default_cstrs; sc_cstrs = default_cstrs; + zk_cstrs = default_cstrs; } (** {2 Generators} *) @@ -229,6 +231,7 @@ let gen_ctxt_req : ctxt_cstrs -> ctxt_req QCheck2.Gen.t = del_cstrs; tx_cstrs; sc_cstrs; + zk_cstrs; } -> let open QCheck2.Gen in let* hard_gas_limit_per_block = gen_gas_integral hard_gas_limit_per_block in @@ -236,7 +239,8 @@ let gen_ctxt_req : ctxt_cstrs -> ctxt_req QCheck2.Gen.t = let* fund_dest = gen_tez dest_cstrs in let* fund_del = gen_tez del_cstrs in let* fund_tx = gen_tez tx_cstrs in - let+ fund_sc = gen_tez sc_cstrs in + let* fund_sc = gen_tez sc_cstrs in + let+ fund_zk = gen_tez zk_cstrs in { hard_gas_limit_per_block; fund_src; @@ -244,6 +248,7 @@ let gen_ctxt_req : ctxt_cstrs -> ctxt_req QCheck2.Gen.t = fund_del; fund_tx; fund_sc; + fund_zk; flags = all_enabled; } diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml index 9dc378dffc4a6611090dc6ae2b7d8d364d95e040..7c59b71b92facefc74e477db86fe14286b1a756b 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -43,6 +43,7 @@ type ctxt = { originated_contract : Contract_hash.t; tx_rollup : Tx_rollup.t option; sc_rollup : Sc_rollup.t option; + zk_rollup : Zk_rollup.t option; } (** Accounts manipulated in the tests. By convention, each field name @@ -56,6 +57,7 @@ type accounts = { del : Account.t option; tx : Account.t option; sc : Account.t option; + zk : Account.t option; } (** Infos describes the information of the setting for a test: the @@ -95,6 +97,7 @@ type manager_operation_kind = | K_Sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond | K_Dal_publish_slot_header + | K_Zk_rollup_origination (** The requirements for a tested manager operation. *) type operation_req = { @@ -108,7 +111,7 @@ type operation_req = { } (** Feature flags requirements for a context setting for a test. *) -type feature_flags = {dal : bool; scoru : bool; toru : bool} +type feature_flags = {dal : bool; scoru : bool; toru : bool; zkru : bool} (** The requirements for a context setting for a test. *) type ctxt_req = { @@ -118,6 +121,7 @@ type ctxt_req = { fund_del : Tez.t option; fund_tx : Tez.t option; fund_sc : Tez.t option; + fund_zk : Tez.t option; flags : feature_flags; } @@ -130,7 +134,7 @@ type ctxt_req = { type mode = Construction | Mempool | Application (** {2 Default values} *) -let all_enabled = {dal = true; scoru = true; toru = true} +let all_enabled = {dal = true; scoru = true; toru = true; zkru = true} let disabled_dal = {all_enabled with dal = false} @@ -138,6 +142,8 @@ let disabled_scoru = {all_enabled with scoru = false} let disabled_toru = {all_enabled with toru = false} +let disabled_zkru = {all_enabled with zkru = false} + let ctxt_req_default_to_flag flags = { hard_gas_limit_per_block = None; @@ -146,6 +152,7 @@ let ctxt_req_default_to_flag flags = fund_del = Some Tez.one; fund_tx = Some Tez.one; fund_sc = Some Tez.one; + fund_zk = Some Tez.one; flags; } @@ -191,6 +198,7 @@ let kind_to_string = function | K_Sc_rollup_execute_outbox_message -> "Sc_rollup_execute_outbox_message" | K_Sc_rollup_recover_bond -> "Sc_rollup_recover_bond" | K_Dal_publish_slot_header -> "Dal_publish_slot_header" + | K_Zk_rollup_origination -> "Zk_rollup_origination" (** {2 Pretty-printers} *) let pp_opt pp v = @@ -241,6 +249,7 @@ let pp_ctxt_req pp fund_del; fund_tx; fund_sc; + fund_zk; flags; } = Format.fprintf @@ -252,9 +261,11 @@ let pp_ctxt_req pp fund_del: %a tz@,\ fund_tx: %a tz@,\ fund_sc: %a tz@,\ + fund_zk: %a tz@,\ dal_flag: %a@,\ scoru_flag: %a@,\ toru_flag: %a@,\ + zkru_flag: %a@,\ @]" (pp_opt Gas.Arith.pp_integral) hard_gas_limit_per_block @@ -268,12 +279,16 @@ let pp_ctxt_req pp fund_tx (pp_opt Tez.pp) fund_sc + (pp_opt Tez.pp) + fund_zk Format.pp_print_bool flags.dal Format.pp_print_bool flags.scoru Format.pp_print_bool flags.toru + Format.pp_print_bool + flags.zkru let pp_mode pp = function | Construction -> Format.fprintf pp "Construction" @@ -357,6 +372,28 @@ let originate_sc_rollup block rollup_account = let+ block = Block.bake ~operation:rollup_origination block in (block, sc_rollup) +module ZKOperator = Dummy_zk_rollup.Operator (struct + let batch_size = 10 +end) + +let originate_zk_rollup block rollup_account = + let open Lwt_result_syntax in + let rollup_contract = contract_of rollup_account in + let* rollup_origination, zk_rollup = + Op.zk_rollup_origination + ~force_reveal:true + (B block) + rollup_contract + ~public_parameters:ZKOperator.public_parameters + ~circuits_info: + (Zk_rollup.Account.SMap.of_seq + @@ Plonk.Main_protocol.SMap.to_seq ZKOperator.circuits) + ~init_state:ZKOperator.init_state + ~nb_ops:1 + in + let+ block = Block.bake ~operation:rollup_origination block in + (block, zk_rollup) + (** {2 Setting's context construction} *) let fund_account block bootstrap account fund = @@ -395,6 +432,7 @@ let init_ctxt : ctxt_req -> infos tzresult Lwt.t = fund_del; fund_tx; fund_sc; + fund_zk; flags; } -> let open Lwt_result_syntax in @@ -415,13 +453,14 @@ let init_ctxt : ctxt_req -> infos tzresult Lwt.t = in let* block, bootstraps = Context.init_n - 6 + 7 ~consensus_threshold:0 ?hard_gas_limit_per_block ~tx_rollup_enable:flags.toru ~tx_rollup_sunset_level:Int32.max_int ~sc_rollup_enable:flags.scoru ~dal_enable:flags.dal + ~zk_rollup_enable:flags.zkru () in let get_bootstrap bootstraps n = Stdlib.List.nth bootstraps n in @@ -438,8 +477,7 @@ let init_ctxt : ctxt_req -> infos tzresult Lwt.t = let* block, tx, tx_rollup = if flags.toru then create_and_fund - ~originate_rollup:(fun infos account -> - originate_tx_rollup infos account) + ~originate_rollup:originate_tx_rollup block (get_bootstrap bootstraps 3) fund_tx @@ -448,23 +486,31 @@ let init_ctxt : ctxt_req -> infos tzresult Lwt.t = let* block, sc, sc_rollup = if flags.scoru then create_and_fund - ~originate_rollup:(fun infos account -> - originate_sc_rollup infos account) + ~originate_rollup:originate_sc_rollup block (get_bootstrap bootstraps 4) fund_sc else return (block, None, None) in + let* block, zk, zk_rollup = + if flags.zkru then + create_and_fund + ~originate_rollup:originate_zk_rollup + block + (get_bootstrap bootstraps 5) + fund_zk + else return (block, None, None) + in let* create_contract_hash, originated_contract = Op.contract_origination_hash (B block) - (get_bootstrap bootstraps 5) + (get_bootstrap bootstraps 6) ~fee:Tez.zero ~script:Op.dummy_script in let+ block = Block.bake ~operation:create_contract_hash block in - let ctxt = {block; originated_contract; tx_rollup; sc_rollup} in - {ctxt; accounts = {source; dest; del; tx; sc}} + let ctxt = {block; originated_contract; tx_rollup; sc_rollup; zk_rollup} in + {ctxt; accounts = {source; dest; del; tx; sc; zk}} (** In addition of building up a context according to a context requirement, source is self-delegated. @@ -642,6 +688,10 @@ let sc_rollup_of = function | Some sc_rollup -> return sc_rollup | None -> failwith "Sc_rollup not created in this context" +let zk_rollup_of = function + | Some zk_rollup -> return zk_rollup + | None -> failwith "Zk_rollup not created in this context" + let mk_tx_rollup_submit_batch (oinfos : operation_req) (infos : infos) = let open Lwt_result_syntax in let* tx_rollup = tx_rollup_of infos.ctxt.tx_rollup in @@ -975,6 +1025,26 @@ let mk_dal_publish_slot_header (oinfos : operation_req) (infos : infos) = (contract_of infos.accounts.source) slot +let mk_zk_rollup_origination (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* op, _ = + Op.zk_rollup_origination + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of infos.accounts.source) + ~public_parameters:ZKOperator.public_parameters + ~circuits_info: + (Zk_rollup.Account.SMap.of_seq + @@ Plonk.Main_protocol.SMap.to_seq ZKOperator.circuits) + ~init_state:ZKOperator.init_state + ~nb_ops:1 + in + return op + (** {2 Helpers for generation of generic check tests by manager operation} *) (** Generic forge for any kind of manager operation according to @@ -1009,6 +1079,7 @@ let select_op (op_req : operation_req) (infos : infos) = | K_Sc_rollup_execute_outbox_message -> mk_sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond -> mk_sc_rollup_return_bond | K_Dal_publish_slot_header -> mk_dal_publish_slot_header + | K_Zk_rollup_origination -> mk_zk_rollup_origination in mk_op op_req infos @@ -1342,6 +1413,7 @@ let subjects = K_Sc_rollup_execute_outbox_message; K_Sc_rollup_recover_bond; K_Dal_publish_slot_header; + K_Zk_rollup_origination; ] let is_consumer = function @@ -1352,7 +1424,7 @@ let is_consumer = function | K_Sc_rollup_add_messages | K_Sc_rollup_origination | K_Sc_rollup_refute | K_Sc_rollup_timeout | K_Sc_rollup_cement | K_Sc_rollup_publish | K_Sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond - | K_Dal_publish_slot_header -> + | K_Dal_publish_slot_header | K_Zk_rollup_origination -> false | K_Transaction | K_Origination | K_Register_global_constant | K_Tx_rollup_dispatch_tickets | K_Transfer_ticket -> @@ -1379,3 +1451,4 @@ let is_disabled flags = function | K_Sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond -> flags.scoru = false | K_Dal_publish_slot_header -> flags.dal = false + | K_Zk_rollup_origination -> flags.zkru = false diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml index 9e4a5a5f4c736a19e45e7eec4ac99b014198b486..ae497adffc3f3b7f7d861bdda1279ab61a6a469b 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml @@ -83,7 +83,8 @@ let ensure_kind infos kind = | Sc_rollup_timeout _, K_Sc_rollup_timeout | Sc_rollup_execute_outbox_message _, K_Sc_rollup_execute_outbox_message | Sc_rollup_recover_bond _, K_Sc_rollup_recover_bond - | Dal_publish_slot_header _, K_Dal_publish_slot_header -> + | Dal_publish_slot_header _, K_Dal_publish_slot_header + | Zk_rollup_origination _, K_Zk_rollup_origination -> return_unit | ( ( Transaction _ | Origination _ | Register_global_constant _ | Delegation _ | Set_deposits_limit _ | Increase_paid_storage _ @@ -95,7 +96,7 @@ let ensure_kind infos kind = | Sc_rollup_cement _ | Sc_rollup_add_messages _ | Sc_rollup_refute _ | Sc_rollup_timeout _ | Sc_rollup_execute_outbox_message _ | Sc_rollup_recover_bond _ | Dal_publish_slot_header _ - | Sc_rollup_dal_slot_subscribe _ ), + | Sc_rollup_dal_slot_subscribe _ | Zk_rollup_origination _ ), _ ) -> assert false) | Single _ -> assert false @@ -683,6 +684,11 @@ let flag_expect_failure flags errs = | [Environment.Ecoproto_error Dal_errors.Dal_feature_disabled] when flags.dal = false -> return_unit + | [ + Environment.Ecoproto_error Validate_errors.Manager.Zk_rollup_feature_disabled; + ] + when flags.zkru = false -> + return_unit | err -> failwith "Error trace:@, %a does not match the expected one" @@ -710,6 +716,7 @@ let test_feature_flags flags kind () = infos.ctxt with tx_rollup = infos_op.ctxt.tx_rollup; sc_rollup = infos_op.ctxt.sc_rollup; + zk_rollup = infos_op.ctxt.zk_rollup; }; } in @@ -753,6 +760,12 @@ let generate_toru_flag () = "Validate with toru disabled." subjects +let generate_zkru_flag () = + create_Tztest + (test_feature_flags disabled_zkru) + "Validate with zkru disabled." + subjects + let sanity_tests = test_ensure_manager_operation_coverage () :: generate_tests_validate () @@ -776,3 +789,4 @@ let contract_tests = let flags_tests = generate_dal_flag () @ generate_toru_flag () @ generate_scoru_flag () + @ generate_zkru_flag () diff --git a/src/proto_alpha/lib_protocol/test/pbt/dune b/src/proto_alpha/lib_protocol/test/pbt/dune index 572d2b9b198894ccd36c725ad02ca25646409475..3d161abf23dd8b1d499f3ea89650e7ec9802afb7 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/dune +++ b/src/proto_alpha/lib_protocol/test/pbt/dune @@ -15,7 +15,8 @@ test_sc_rollup_tick_repr test_sc_rollup_encoding test_refutation_game - test_carbonated_map) + test_carbonated_map + test_zk_rollup_encoding) (libraries tezos-base tezos-micheline @@ -106,3 +107,8 @@ (alias runtest) (package tezos-protocol-alpha-tests) (action (run %{dep:./test_carbonated_map.exe}))) + +(rule + (alias runtest) + (package tezos-protocol-alpha-tests) + (action (run %{dep:./test_zk_rollup_encoding.exe}))) diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_zk_rollup_encoding.ml b/src/proto_alpha/lib_protocol/test/pbt/test_zk_rollup_encoding.ml new file mode 100644 index 0000000000000000000000000000000000000000..95afbc9f3ef9f409f5f0de90c336763edbdb325c --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/pbt/test_zk_rollup_encoding.ml @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec \ + src/proto_alpha/lib_protocol/test/pbt/test_zk_rollup_encoding.exe + Subject: Zk rollup encodings +*) + +open Protocol +open QCheck2 +open Lib_test.Qcheck2_helpers + +(* Generators *) + +let gen_zkr_address = + let open Gen in + let+ bytes = bytes_fixed_gen Zk_rollup_repr.Address.size in + Zk_rollup_repr.Address.of_bytes_exn bytes + +let gen_scalar = + let s = Bls12_381.Fr.random () in + Gen.return s + +let gen_l2_state = + let open Gen in + array gen_scalar + +(* Number of operations in each private batch *) +let batch_size = 10 + +(* We use fixed values for Plonk types, because it's interface + doesn't expose a quick and safe way to create them randomly. *) +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +let nat64 = int64_range_gen 0L Int64.max_int + +let gen_zkr_account = + let open Gen in + let open Zk_rollup_account_repr in + let* state = gen_l2_state in + let public_parameters = Operator.public_parameters in + let circuits_info = + SMap.of_seq (Plonk.Main_protocol.SMap.to_seq Operator.circuits) + in + let+ nb_ops = nat in + let static = + { + public_parameters; + state_length = Array.length state; + circuits_info; + nb_ops; + } + in + let dynamic = {state} in + {static; dynamic} + +let gen_ticket_hash = + let open Gen in + let+ bytes = bytes_fixed_gen Script_expr_hash.size in + Ticket_hash_repr.of_bytes_exn bytes + +let gen_pkh = + let pkh, _, _ = Signature.generate_key ~algo:Ed25519 () in + Gen.return pkh + +let gen_z = + let open Gen in + sized @@ fun n -> map Z.of_bits (string_size (return n)) + +let gen_l2_op = + let open Gen in + let* op_code = nat in + let* price = map2 (fun x y -> (x, y)) gen_ticket_hash gen_z in + let* l1_dst = gen_pkh in + let* rollup_id = gen_zkr_address in + let+ payload = array gen_scalar in + Zk_rollup_operation_repr.{op_code; price; l1_dst; rollup_id; payload} + +let gen_pending_list = + let open Gen in + let open Zk_rollup_repr in + let of_length next_index = function + | 0 -> Empty {next_index} + | length -> Pending {next_index; length} + in + map2 of_length nat64 uint16 + +(* Data-encoding roundtrip tests *) + +let test_roundtrip_address = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup.t" + ~gen:gen_zkr_address + ~eq:( = ) + Zk_rollup_repr.Address.encoding + +let test_roundtrip_state = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_state_repr.t" + ~gen:gen_l2_state + ~eq:( = ) + Zk_rollup_state_repr.encoding + +let eq_account acc0 acc1 = + let open Zk_rollup_account_repr in + let pp_to_bytes pp = + Data_encoding.Binary.to_bytes_exn + Environment.Plonk.public_parameters_encoding + pp + in + acc0.dynamic = acc1.dynamic + && acc0.static.state_length = acc1.static.state_length + && acc0.static.circuits_info = acc1.static.circuits_info + && acc0.static.nb_ops = acc1.static.nb_ops + && pp_to_bytes acc0.static.public_parameters + = pp_to_bytes acc1.static.public_parameters + +let test_roundtrip_account = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_account_repr.t" + ~gen:gen_zkr_account + ~eq:eq_account + Zk_rollup_account_repr.encoding + +let test_roundtrip_operation = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_operation_repr.t" + ~gen:gen_l2_op + ~eq:( = ) + Zk_rollup_operation_repr.encoding + +let test_roundtrip_pending_list = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_repr.pending_list" + ~gen:gen_pending_list + ~eq:( = ) + Zk_rollup_repr.pending_list_encoding + +let tests_roundtrip = + [ + test_roundtrip_address; + test_roundtrip_state; + test_roundtrip_account; + test_roundtrip_operation; + test_roundtrip_pending_list; + ] + +(* Scalar conversion tests *) + +let test_to_scalar ~count ~title ~gen to_scalar = + QCheck2.Test.make + ~count + ~name:(Format.asprintf "to_scalar %s" title) + gen + (fun input -> + try + ignore @@ to_scalar input ; + true + with _ -> false) + +let test_address_to_scalar = + test_to_scalar + ~count:1_000 + ~title:"Zk_rollup_repr.t" + ~gen:gen_zkr_address + Zk_rollup_repr.to_scalar + +let test_operation_to_scalar = + test_to_scalar + ~count:1_000 + ~title:"Zk_rollup_operation.t" + ~gen:gen_l2_op + Zk_rollup_operation_repr.to_scalar_array + +let tests_to_scalar = [test_address_to_scalar; test_operation_to_scalar] + +let () = + Alcotest.run + "ZK rollup encoding" + [ + ("roundtrip", qcheck_wrap tests_roundtrip); + ("to_scalar", qcheck_wrap tests_to_scalar); + ] diff --git a/src/proto_alpha/lib_protocol/test/unit/main.ml b/src/proto_alpha/lib_protocol/test/unit/main.ml index ac07dd5d4e3799017a28aa80c2e839174ad1c7eb..21fbb6db3e51317f8be37112acb6046729f4c450 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -82,5 +82,6 @@ let () = "sc rollup management protocol" Test_sc_rollup_management_protocol.tests; Unit_test.spec "Bond_id_repr.ml" Test_bond_id_repr.tests; + Unit_test.spec "zk rollup storage" Test_zk_rollup_storage.tests; ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/unit/test_zk_rollup_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_zk_rollup_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..ffcf640b9aa27675c7f961ecc8a55ab115d972fa --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_zk_rollup_storage.ml @@ -0,0 +1,145 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Zk_rollup) + Invocation: cd src/proto_alpha/lib_protocol/test/unit && \ + dune exec ./main.exe -- test "^\[Unit\] zk rollup storage$" + Subject: On ZK Rollup storage +*) + +open Protocol + +let wrap e = Lwt.return (Environment.wrap_tzresult e) + +let ( let** ) m f = + let open Lwt_result_syntax in + let* x = m >>= wrap in + f x + +let batch_size = 10 + +module ZKRU = struct + include Alpha_context.Zk_rollup + + type pkh = Signature.Public_key_hash.t + + let pkh_encoding = Signature.Public_key_hash.encoding + + type ticket_hash = Alpha_context.Ticket_hash.t + + let ticket_hash_encoding = Alpha_context.Ticket_hash.encoding +end + +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +let no_ticket op = (op, None) + +module Raw_context_tests = struct + module Helpers = struct + let is_empty : Zk_rollup_repr.pending_list -> bool = function + | Zk_rollup_repr.Empty _ -> true + | _ -> false + + let pending_length : Zk_rollup_repr.pending_list -> int = + let open Zk_rollup_repr in + function Empty _ -> 0 | Pending {length; _} -> length + + let get_pending_list = + let open Lwt_result_syntax in + let open Zk_rollup_repr in + fun ctx rollup -> function + | Empty _ -> return (ctx, []) + | Pending {next_index; length} -> + let head = Int64.(sub next_index (of_int length)) in + let to_get = + Stdlib.List.init length (fun x -> Int64.(add (of_int x) head)) + in + let* ctx, ops = + List.fold_left_es + (fun (ctx, acc) i -> + let** ctx, op = + Storage.Zk_rollup.Pending_operation.get (ctx, rollup) i + in + return (ctx, op :: acc)) + (ctx, []) + to_get + in + return (ctx, List.rev ops) + end + + let initial_ctx () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 () in + let** ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + in + let nonce = Operation_hash.hash_string ["nonce_hash"] in + return (Raw_context.init_origination_nonce ctx nonce, contract) + + (* Context with an originated ZKRU *) + let originate_ctx () = + let open Lwt_result_syntax in + let open Zk_rollup_account_repr in + let* ctx, contract = initial_ctx () in + let public_parameters = Operator.public_parameters in + let state = Operator.init_state in + let state_length = Array.length state in + let circuits_info = + SMap.of_seq @@ Plonk.Main_protocol.SMap.to_seq Operator.circuits + in + let nb_ops = 1 in + let* ctx, rollup, _size = + Zk_rollup_storage.originate + ctx + {public_parameters; state_length; circuits_info; nb_ops} + ~init_state:state + >>= wrap + in + return (ctx, rollup, contract) + + (* Check that the pending list of a new ZKRU is empty *) + let pending_list_origination_is_empty () = + let open Lwt_result_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let** _ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.is_empty pending) ; + return_unit +end + +let tests = + [ + Tztest.tztest + "origination_pending_is_empty" + `Quick + Raw_context_tests.pending_list_origination_is_empty; + ] diff --git a/src/proto_alpha/lib_protocol/validate_errors.ml b/src/proto_alpha/lib_protocol/validate_errors.ml index 52b0f78dbf077ba079d26ed91ce6be0e023f16e2..00f517d5a3c5ae9abc07c39d52105ec3d1d2107e 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.ml +++ b/src/proto_alpha/lib_protocol/validate_errors.ml @@ -1044,6 +1044,7 @@ module Manager = struct | Gas_quota_exceeded_init_deserialize | Tx_rollup_feature_disabled | Sc_rollup_feature_disabled + | Zk_rollup_feature_disabled let () = register_error_kind @@ -1160,7 +1161,19 @@ module Manager = struct ~pp:(fun ppf () -> Format.fprintf ppf "%s" scoru_disabled_description) Data_encoding.unit (function Sc_rollup_feature_disabled -> Some () | _ -> None) - (fun () -> Sc_rollup_feature_disabled) + (fun () -> Sc_rollup_feature_disabled) ; + let zkru_disabled_description = + "ZK rollups will be enabled in a future proposal." + in + register_error_kind + `Permanent + ~id:"validate_operation.zk_rollup_disabled" + ~title:"ZK rollups are disabled" + ~description:zkru_disabled_description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" zkru_disabled_description) + Data_encoding.unit + (function Zk_rollup_feature_disabled -> Some () | _ -> None) + (fun () -> Zk_rollup_feature_disabled) end type error += Failing_noop_error diff --git a/src/proto_alpha/lib_protocol/validate_errors.mli b/src/proto_alpha/lib_protocol/validate_errors.mli index 2ff8a6403301ec2ed3b335094b680d9882fc72ef..2d52451bdf471e8844f07edc872df98bd4da9f4a 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.mli +++ b/src/proto_alpha/lib_protocol/validate_errors.mli @@ -178,6 +178,7 @@ module Manager : sig | Gas_quota_exceeded_init_deserialize | Tx_rollup_feature_disabled | Sc_rollup_feature_disabled + | Zk_rollup_feature_disabled end type error += Failing_noop_error diff --git a/src/proto_alpha/lib_protocol/validate_operation.ml b/src/proto_alpha/lib_protocol/validate_operation.ml index 522b12506d020d54290e0c67fafc83a08279d4dc..bd2dd89c7f26ec04e44e674008097c38aa7c763d 100644 --- a/src/proto_alpha/lib_protocol/validate_operation.ml +++ b/src/proto_alpha/lib_protocol/validate_operation.ml @@ -1623,6 +1623,9 @@ module Manager = struct | [] -> error Sc_rollup_errors.Sc_rollup_add_zero_messages | _ -> ok () + let assert_zk_rollup_feature_enabled vi = + error_unless (Constants.zk_rollup_enable vi.ctxt) Zk_rollup_feature_disabled + let consume_decoding_gas ctxt lexpr = record_trace Gas_quota_exceeded_init_deserialize @@ (* Fail early if the operation does not have enough gas to @@ -1801,6 +1804,9 @@ module Manager = struct | Dal_publish_slot_header {slot} -> let* () = Dal_apply.validate_publish_slot_header vi.ctxt slot in return remaining_gas + | Zk_rollup_origination _ -> + let* () = assert_zk_rollup_feature_enabled vi in + return remaining_gas in let* balance, is_allocated = Contract.simulate_spending diff --git a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..06ed67a39712aa4a84bdc4fb71abda18a9a763ed --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module SMap = Map.Make (String) + +type static = { + public_parameters : Plonk.public_parameters; + state_length : int; + circuits_info : bool SMap.t; + nb_ops : int; +} + +type dynamic = {state : Zk_rollup_state_repr.t} + +type t = {static : static; dynamic : dynamic} + +let encoding = + let open Data_encoding in + let static_encoding = + let circuits_info_encoding = + conv + (fun m -> List.of_seq @@ SMap.to_seq m) + (fun l -> SMap.of_seq @@ List.to_seq l) + (list (tup2 string bool)) + in + conv + (fun {public_parameters; state_length; circuits_info; nb_ops} -> + (public_parameters, state_length, circuits_info, nb_ops)) + (fun (public_parameters, state_length, circuits_info, nb_ops) -> + {public_parameters; state_length; circuits_info; nb_ops}) + (obj4 + (req "public_parameters" Plonk.public_parameters_encoding) + (req "state_length" int31) + (req "circuits_info" circuits_info_encoding) + (req "nb_ops" int31)) + in + let dynamic_encoding = + conv + (fun {state} -> state) + (fun state -> {state}) + (obj1 (req "state" Zk_rollup_state_repr.encoding)) + in + conv + (fun {static; dynamic} -> (static, dynamic)) + (fun (static, dynamic) -> {static; dynamic}) + (obj2 (req "static" static_encoding) (req "dynamic" dynamic_encoding)) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..37b4eae02b04d32b68c00e4be377507f6ea1272d --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module SMap : Map.S with type key = string + +(** Representation of a ZK Rollup account. *) + +(** Static part of a ZKRU account. These are set at origination, + after which they cannot be modified. *) +type static = { + public_parameters : Plonk.public_parameters; + (** Input to the Plonk verifier that are fixed once the circuits + are decided. *) + state_length : int; (** Number of scalars in the state. *) + circuits_info : bool SMap.t; + (** Circuit names, alongside a boolean flag indicating + if they can be used for private ops. *) + nb_ops : int; (** Valid op codes of L2 operations must be in \[0, nb_ops) *) +} + +(** Dynamic part of a ZKRU account. *) +type dynamic = { + state : Zk_rollup_state_repr.t; + (** Array of scalars representing the state of the rollup + at a given level. *) +} + +type t = {static : static; dynamic : dynamic} + +val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/zk_rollup_apply.ml b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml new file mode 100644 index 0000000000000000000000000000000000000000..df361b65d1ba11f4d167f050403bbb9e5ffdb981 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Zk_rollup_feature_disabled | Zk_rollup_negative_nb_ops + +let () = + let description = "ZK rollups will be enabled in a future proposal." in + register_error_kind + `Permanent + ~id:"operation.zk_rollup_disabled" + ~title:"ZK rollups are disabled" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Zk_rollup_feature_disabled -> Some () | _ -> None) + (fun () -> Zk_rollup_feature_disabled) ; + let description = "The value of [nb_ops] should never be negative." in + register_error_kind + `Permanent + ~id:"operation.zk_rollup_negative_nb_ops" + ~title:"ZK rollups negative number of operations" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Zk_rollup_negative_nb_ops -> Some () | _ -> None) + (fun () -> Zk_rollup_negative_nb_ops) + +let assert_feature_enabled ctxt = + fail_unless (Constants.zk_rollup_enable ctxt) Zk_rollup_feature_disabled + +let originate ~ctxt_before_op ~ctxt ~public_parameters ~circuits_info + ~init_state ~nb_ops = + assert_feature_enabled ctxt >>=? fun () -> + fail_when Compare.Int.(nb_ops < 0) Zk_rollup_negative_nb_ops >>=? fun () -> + Zk_rollup.originate + ctxt + { + public_parameters; + state_length = Array.length init_state; + circuits_info; + nb_ops; + } + ~init_state + >>=? fun (ctxt, originated_zk_rollup, size) -> + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Apply_results.Zk_rollup_origination_result + { + balance_updates = []; + originated_zk_rollup; + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + consumed_gas; + size; + } + in + return (ctxt, result, []) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_apply.mli b/src/proto_alpha/lib_protocol/zk_rollup_apply.mli new file mode 100644 index 0000000000000000000000000000000000000000..c54761db5e9178d85a2168f97a85f6d19cdaf302 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_apply.mli @@ -0,0 +1,76 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module handles all the validation/application of any operation + related to the ZK Rollup. + All of the functions defined in this module require that the ZKRU + feature flag is enabled. +*) + +open Alpha_context + +(** These errors are only to be matched in tests. *) +type error += + | Zk_rollup_feature_disabled + (** Emitted when trying to apply a ZK Rollup operation while the ZKRU + feature flag is not active. *) + | Zk_rollup_negative_nb_ops + (** Emitted when originating a ZK Rollup with a negative [nb_ops]. *) + +(** [assert_feature_enabled ctxt] asserts that the ZK Rollup feature flag + is activated. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated.} + } +*) +val assert_feature_enabled : t -> unit tzresult Lwt.t + +(** [originate ~ctxt_before_op ~ctxt ~public_parameters ~transcript + ~circuits_info ~init_state ~nb_ops] + applies the origination operation for a ZK rollup. + See {!Zk_rollup_storage:originate}. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated.} + {li [Zk_rollup_negative_nb_ops] if [nb_ops] is negative.} + } +*) +val originate : + ctxt_before_op:t -> + ctxt:t -> + public_parameters:Plonk.public_parameters -> + circuits_info:bool Zk_rollup.Account.SMap.t -> + init_state:Zk_rollup.State.t -> + nb_ops:int -> + (t + * Kind.zk_rollup_origination Apply_results.successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t diff --git a/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..f020df556484fedcafaeafd16ed02af05ad0d240 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + op_code : int; + price : Ticket_hash_repr.t * Z.t; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Zk_rollup_repr.t; + payload : Zk_rollup_scalar.t array; +} + +let int_to_scalar x = Zk_rollup_scalar.of_z (Z.of_int x) + +let pkh_to_scalar x = + Zk_rollup_scalar.of_bytes + (Data_encoding.Binary.to_bytes_exn Signature.Public_key_hash.encoding x) + +let ticket_hash_to_scalar ticket_hash = + Zk_rollup_scalar.of_bytes + @@ Data_encoding.Binary.to_bytes_exn Ticket_hash_repr.encoding ticket_hash + +let to_scalar_array {op_code; price; l1_dst; rollup_id; payload} = + Array.concat + [ + [| + int_to_scalar op_code; + ticket_hash_to_scalar (fst price); + Zk_rollup_scalar.of_z (snd price); + pkh_to_scalar l1_dst; + Zk_rollup_repr.to_scalar rollup_id; + |]; + payload; + ] + +let encoding = + Data_encoding.( + conv + (fun {op_code; price; l1_dst; rollup_id; payload} -> + (op_code, price, l1_dst, rollup_id, payload)) + (fun (op_code, price, l1_dst, rollup_id, payload) -> + {op_code; price; l1_dst; rollup_id; payload}) + (obj5 + (req "op_code" int31) + (req "price" (tup2 Ticket_hash_repr.encoding z)) + (req "l1_dst" Signature.Public_key_hash.encoding) + (req "rollup_id" Zk_rollup_repr.Address.encoding) + (req "payload" Plonk.scalar_array_encoding))) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..1e3542ea7c4bc66bccf3c3e68a35022625b304d6 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A ZK rollup L2 operation has two parts: a transparent header and + an opaque payload. + The header is made up by: + {ul + {li An [op_code] in the range \[0, nb_ops)} + {li [price = (ticket_hash, amount)] where [ticket_hash] is used as + a ticket identifier, and [amount] positive if the operation transfers + tickets from L1 to L2, negative if it does so from L2 to L1, and zero + when no transfer is done between layers} + {li [l1_dst] is the public key hash of the implicit account that will + be credited with the withdrawal generated by this operation, if any} + {li [rollup_id] is the address of the rollup this operation targets} + } + + This type represents the L1's view of L2 operations. It's important + to remember that this is only used for public operations, as the + protocol isn't aware of private ones. +*) +type t = { + op_code : int; + price : Ticket_hash_repr.t * Z.t; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Zk_rollup_repr.t; + payload : Zk_rollup_scalar.t array; +} + +val encoding : t Data_encoding.t + +(** Special encoding needed to feed L2 operations to the Plonk verifier *) +val to_scalar_array : t -> Zk_rollup_scalar.t array diff --git a/src/proto_alpha/lib_protocol/zk_rollup_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..35497192cc9a4cfb8733d9b4120008f135270295 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_repr.ml @@ -0,0 +1,149 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Address = struct + let prefix = "zkr1" + + let encoded_size = 37 + + let decoded_prefix = "\001\171\084\251" + + module H = + Blake2B.Make + (Base58) + (struct + let name = "Zk_rollup_hash" + + let title = "A zk rollup address" + + let b58check_prefix = decoded_prefix + + let size = Some 20 + end) + + include H + + let () = Base58.check_encoded_prefix b58check_encoding prefix encoded_size + + include Path_encoding.Make_hex (H) + + type error += (* `Permanent *) Error_zk_rollup_address_generation + + let () = + let open Data_encoding in + let msg = "Error while generating rollup address" in + register_error_kind + `Permanent + ~id:"rollup.error_zk_rollup_address_generation" + ~title:msg + ~pp:(fun ppf () -> Format.fprintf ppf "%s" msg) + ~description:msg + unit + (function Error_zk_rollup_address_generation -> Some () | _ -> None) + (fun () -> Error_zk_rollup_address_generation) + + let from_nonce nonce = + Data_encoding.Binary.to_bytes_opt Origination_nonce.encoding nonce + |> function + | None -> error Error_zk_rollup_address_generation + | Some nonce -> ok @@ hash_bytes [nonce] + + let of_b58data = function H.Data h -> Some h | _ -> None +end + +type t = Address.t + +let to_scalar x = + Zk_rollup_scalar.of_bytes + (Data_encoding.Binary.to_bytes_exn Address.encoding x) + +type pending_list = + | Empty of {next_index : int64} + | Pending of {next_index : int64; length : int} + +let pending_list_encoding : pending_list Data_encoding.t = + let open Data_encoding in + let empty_tag, pending_tag = (0, 1) in + let empty_encoding = + obj1 (req "next_index" Compact.(make ~tag_size:`Uint8 int64)) + in + let pending_encoding = + obj2 + (req "next_index" Compact.(make ~tag_size:`Uint8 int64)) + (req "length" uint16) + in + matching + (function + | Empty {next_index} -> matched empty_tag empty_encoding next_index + | Pending {next_index; length} -> + matched pending_tag pending_encoding (next_index, length)) + [ + case + ~title:"Empty" + (Tag empty_tag) + empty_encoding + (function Empty {next_index} -> Some next_index | _ -> None) + (fun next_index -> Empty {next_index}); + case + ~title:"Pending" + (Tag pending_tag) + pending_encoding + (function + | Pending {next_index; length} -> Some (next_index, length) + | _ -> None) + (fun (next_index, length) -> Pending {next_index; length}); + ] + +module Index = struct + type nonrec t = t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn Address.encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt Address.encoding) + | _ -> None + + let rpc_arg = Address.rpc_arg + + let encoding = Address.encoding + + let compare = Address.compare +end + +module Internal_for_tests = struct + let originated_zk_rollup nonce = + let data = + Data_encoding.Binary.to_bytes_exn Origination_nonce.encoding nonce + in + Address.hash_bytes [data] +end diff --git a/src/proto_alpha/lib_protocol/zk_rollup_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..c8c940840fd5b8f0895b8a42c7f97d32a08204d4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_repr.mli @@ -0,0 +1,66 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A ZK rollup has an address starting with "zkr1". + ZKRU addresses have a length of 20 bytes, which means + that they have an injective encoding as BLS12-381 scalars. +*) +module Address : sig + include S.HASH + + (** [from_nonce nonce] produces an address completely determined by + an operation hash and an origination counter. *) + val from_nonce : Origination_nonce.t -> t tzresult + + (** [encoded_size] is the number of bytes needed to represent an address. *) + val encoded_size : int + + val of_b58data : Base58.data -> t option + + val prefix : string +end + +type t = Address.t + +(** [to_scalar address] returns the scalar corresponding to [address] *) +val to_scalar : t -> Zk_rollup_scalar.t + +(** Description of a ZK rollup's pending list. *) +type pending_list = + | Empty of {next_index : int64} + (** Empty pending list but starting point will be [next_index] + when adding to the list *) + | Pending of {next_index : int64; length : int} + (** Pending list with + [(next_index - length) .. (next_index - 1)]. + [length] is encoded as a [uint16]. *) + +val pending_list_encoding : pending_list Data_encoding.t + +module Index : Storage_description.INDEX with type t = t + +module Internal_for_tests : sig + val originated_zk_rollup : Origination_nonce.t -> Address.t +end diff --git a/src/proto_alpha/lib_protocol/zk_rollup_scalar.ml b/src/proto_alpha/lib_protocol/zk_rollup_scalar.ml new file mode 100644 index 0000000000000000000000000000000000000000..1bdc3d01a05e6e9f8e121bf32085fba4d99dc604 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_scalar.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Bls12_381.Fr.t + +let of_z z = + (* In case [z] is outside of the field, i.e. Z >= Fr.order, + [Bls12_381.Fr.of_z] will apply a modulo reduction to ge + t a field element *) + Bls12_381.Fr.of_z z + +let of_bytes bs = + (* The bytes are interpreted as a Z integer *) + let z = Z.of_bits @@ Bytes.to_string bs in + of_z z diff --git a/src/proto_alpha/lib_protocol/zk_rollup_scalar.mli b/src/proto_alpha/lib_protocol/zk_rollup_scalar.mli new file mode 100644 index 0000000000000000000000000000000000000000..2cfce7d9ee2f1fe733be15b30ba1a6bc025f0305 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_scalar.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Representation of scalars used by the ZK Rollup alongside + manipulation functions *) + +(** Scalars are transparently BLS12-381 scalars *) +type t = Bls12_381.Fr.t + +(** Safe conversion from Z.t. + If the numerical value is not in the field, modulo reduction + is applied. *) +val of_z : Z.t -> t + +(** Safe conversion from bytes. + If the numerical value is not in the field, modulo reduction + is applied. *) +val of_bytes : bytes -> t diff --git a/src/proto_alpha/lib_protocol/zk_rollup_state_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_state_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..64ccb1bdde37354dfc0c2101d38d6da35e11a30c --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_state_repr.ml @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Zk_rollup_scalar.t array + +let encoding = Plonk.scalar_array_encoding diff --git a/src/proto_alpha/lib_protocol/zk_rollup_state_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_state_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..359074016ab08908ef1f47dae71e725fb7474cbf --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_state_repr.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The state of a ZK Rollup is an opaque array of scalars, and represents + the L1's view of the L2 state. + Although the length of this array is unbound, this type should describe + a succinct representation of the entire RU state. Upon origination, the + length of a ZKRU's state is fixed. +*) +type t = Zk_rollup_scalar.t array + +val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/zk_rollup_storage.ml b/src/proto_alpha/lib_protocol/zk_rollup_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..db68462ca975e9bb6e7110a600c1f8812585e3b8 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_storage.ml @@ -0,0 +1,58 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Zk_rollup_does_not_exist of Zk_rollup_repr.t + +let () = + register_error_kind + `Temporary + ~id:"Zk_rollup_does_not_exist" + ~title:"ZK Rollup does not exist" + ~description:"Attempted to use a ZK rollup that has not been originated." + ~pp:(fun ppf x -> + Format.fprintf ppf "Rollup %a does not exist" Zk_rollup_repr.Address.pp x) + Data_encoding.(obj1 (req "rollup" Zk_rollup_repr.Address.encoding)) + (function Zk_rollup_does_not_exist x -> Some x | _ -> None) + (fun x -> Zk_rollup_does_not_exist x) + +let originate ctxt static ~init_state = + let open Lwt_result_syntax in + let*? ctxt, nonce = Raw_context.increment_origination_nonce ctxt in + let*? address = Zk_rollup_repr.Address.from_nonce nonce in + let initial_account = + Zk_rollup_account_repr.{static; dynamic = {state = init_state}} + in + let* ctxt, account_size = + Storage.Zk_rollup.Account.init ctxt address initial_account + in + let init_pl = Zk_rollup_repr.(Empty {next_index = 0L}) in + let* ctxt, pl_size = + Storage.Zk_rollup.Pending_list.init ctxt address init_pl + in + let address_size = Zk_rollup_repr.Address.size in + let size = Z.of_int (address_size + account_size + pl_size) in + return (ctxt, address, size) + +let exists ctxt rollup = Storage.Zk_rollup.Account.mem ctxt rollup diff --git a/src/proto_alpha/lib_protocol/zk_rollup_storage.mli b/src/proto_alpha/lib_protocol/zk_rollup_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..35ae4b42b6dcf6de83a5bfd7ff4c49e5544f241a --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_storage.mli @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** These errors are only to be matched in tests. *) +type error += + | Zk_rollup_does_not_exist of Zk_rollup_repr.t + (** Emitted when trying to perform an operation over a ZK rollup + that hasn't been initialised. *) + +(** [originate context static ~init_state] produces an address [a] for + a ZK rollup storage using the [origination_nonce] from + the [context]. This function also initializes the storage, + indexing the initial ZKRU account by [a]. + + Returns the new context and ZKRU address, alongside the size + of the new account. +*) +val originate : + Raw_context.t -> + Zk_rollup_account_repr.static -> + init_state:Zk_rollup_state_repr.t -> + (Raw_context.t * Zk_rollup_repr.t * Z.t) tzresult Lwt.t + +(** [exists context rollup] returns a boolean representing whether + [rollup] has been initialized. +*) +val exists : + Raw_context.t -> Zk_rollup_repr.t -> (Raw_context.t * bool) tzresult Lwt.t diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out index d0820eac95fd49ea77d5bc4f82a49251be7e8258..5b74758fa4ea2815f6ac6387ae22e0ed9b1815a0 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out @@ -58,7 +58,8 @@ "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out index 8e88f208fcd9b030e4ee891f8b862a3676f7cc97..e6cf8ebf86271f958c193a63082ab7da8a85a97f 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out @@ -58,7 +58,8 @@ "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode light rpc get /chains/main/blocks/head/helpers/baking_rights diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out index 2e32dff28cc8ee4f041352cff91a0f0de1232220..664cafae0909b7c4e480e9ade7bb5ba594f50e3f 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out @@ -58,7 +58,8 @@ "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode proxy rpc get /chains/main/blocks/head/helpers/baking_rights diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out index 5b37e1c8add2ba6317807712ea378376e986a2cd..c5b98962d41281e95a80f6ce3e4499fe367bc30a 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out @@ -58,7 +58,8 @@ "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out index 5b37e1c8add2ba6317807712ea378376e986a2cd..c5b98962d41281e95a80f6ce3e4499fe367bc30a 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out @@ -58,7 +58,8 @@ "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", diff --git a/tezt/tests/expected/sc_rollup.ml/Alpha- arith - rollup node - correct handling of commitments (no_commitment_publ.out b/tezt/tests/expected/sc_rollup.ml/Alpha- arith - rollup node - correct handling of commitments (no_commitment_publ.out index 1eb7c4c5b44eff1199d12b4efeb9a9b074a35b34..388065fd3fb2c9160a88ffeb822f4b338d54c231 100644 --- a/tezt/tests/expected/sc_rollup.ml/Alpha- arith - rollup node - correct handling of commitments (no_commitment_publ.out +++ b/tezt/tests/expected/sc_rollup.ml/Alpha- arith - rollup node - correct handling of commitments (no_commitment_publ.out @@ -114,7 +114,8 @@ This sequence of operations was run: "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for sc rollup '[SC_ROLLUP_HASH]' --fee 1 Node is bootstrapped. @@ -223,7 +224,8 @@ This sequence of operations was run: "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for sc rollup '[SC_ROLLUP_HASH]' --fee 1 Node is bootstrapped. diff --git a/tezt/tests/expected/sc_rollup.ml/Alpha- wasm_2_0_0 - rollup node - correct handling of commitments (no_commitment.out b/tezt/tests/expected/sc_rollup.ml/Alpha- wasm_2_0_0 - rollup node - correct handling of commitments (no_commitment.out index f50f0fa077db28b70bf90b65316159a6fbe718e1..1f795fac08fb33ec0b44a6894a5c039d513f6b4a 100644 --- a/tezt/tests/expected/sc_rollup.ml/Alpha- wasm_2_0_0 - rollup node - correct handling of commitments (no_commitment.out +++ b/tezt/tests/expected/sc_rollup.ml/Alpha- wasm_2_0_0 - rollup node - correct handling of commitments (no_commitment.out @@ -114,7 +114,8 @@ This sequence of operations was run: "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for sc rollup '[SC_ROLLUP_HASH]' --fee 1 Node is bootstrapped. @@ -223,7 +224,8 @@ This sequence of operations was run: "sc_rollup_max_outbox_messages_per_level": 100, "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, - "sc_rollup_max_number_of_cemented_commitments": 5 } + "sc_rollup_max_number_of_cemented_commitments": 5, + "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } ./tezos-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for sc rollup '[SC_ROLLUP_HASH]' --fee 1 Node is bootstrapped.