diff --git a/src/proto_alpha/bin_sc_rollup_node/daemon.ml b/src/proto_alpha/bin_sc_rollup_node/daemon.ml index c42894c07ccb52dd3e96b754bb6f0b3ba05ac30d..24b860f6a08bf03703463a40c7528316568c7b5a 100644 --- a/src/proto_alpha/bin_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/bin_sc_rollup_node/daemon.ml @@ -161,7 +161,7 @@ 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 _ - | Sc_rollup_originate _ | Zk_rollup_origination _ -> + | Sc_rollup_originate _ | Zk_rollup_origination _ | Zk_rollup_publish _ -> 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 5b90225165ec25ea68236e1d70d596d4764aa485..982460e53953e6c87c7999ab26577bf922975ea7 100644 --- a/src/proto_alpha/bin_sc_rollup_node/injector.ml +++ b/src/proto_alpha/bin_sc_rollup_node/injector.ml @@ -150,7 +150,8 @@ 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 _ | Zk_rollup_origination _ -> + | Sc_rollup_dal_slot_subscribe _ | Zk_rollup_origination _ + | Zk_rollup_publish _ -> (* These operations should never be handled by this injector *) assert false diff --git a/src/proto_alpha/lib_benchmark/michelson_samplers.ml b/src/proto_alpha/lib_benchmark/michelson_samplers.ml index cfbf55b03d527c914e78dc3370c0687a61949c16..82cca5fff8cff71b2231796ed428283278dde97d 100644 --- a/src/proto_alpha/lib_benchmark/michelson_samplers.ml +++ b/src/proto_alpha/lib_benchmark/michelson_samplers.ml @@ -595,7 +595,7 @@ end) if b then let* tx_rollup = tx_rollup in let destination = Alpha_context.Destination.Tx_rollup tx_rollup in - let entrypoint = Alpha_context.Tx_rollup.deposit_entrypoint in + let entrypoint = Alpha_context.Entrypoint.deposit in return (Typed_contract.Internal_for_tests.typed_exn arg_ty diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 6e982c8c9a4aa711407722a3a436ac000e3c6523..b771c51f1e4150e0c3a3b7dde4e88a557fb53af9 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -310,7 +310,8 @@ let estimated_gas_single (type kind) | Transaction_result ( Transaction_to_contract_result {consumed_gas; _} | Transaction_to_tx_rollup_result {consumed_gas; _} - | Transaction_to_sc_rollup_result {consumed_gas; _} ) + | Transaction_to_sc_rollup_result {consumed_gas; _} + | Transaction_to_zk_rollup_result {consumed_gas; _} ) | Origination_result {consumed_gas; _} | Reveal_result {consumed_gas} | Delegation_result {consumed_gas} @@ -336,9 +337,10 @@ 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; _} - | Zk_rollup_origination_result {consumed_gas; _} -> - Ok consumed_gas) + | Sc_rollup_dal_slot_subscribe_result {consumed_gas; _} -> + Ok consumed_gas + | Zk_rollup_origination_result {consumed_gas; _} -> Ok consumed_gas + | Zk_rollup_publish_result {consumed_gas; _} -> Ok consumed_gas) | Skipped _ -> error_with "Cannot estimate gas of skipped operation" (* There must be another error for this to happen, and it should not @@ -353,7 +355,8 @@ let estimated_gas_single (type kind) | ITransaction_result ( Transaction_to_contract_result {consumed_gas; _} | Transaction_to_tx_rollup_result {consumed_gas; _} - | Transaction_to_sc_rollup_result {consumed_gas; _} ) + | Transaction_to_sc_rollup_result {consumed_gas; _} + | Transaction_to_zk_rollup_result {consumed_gas; _} ) | IOrigination_result {consumed_gas; _} | IDelegation_result {consumed_gas} | IEvent_result {consumed_gas} -> @@ -392,7 +395,10 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size | Tx_rollup_submit_batch_result {paid_storage_size_diff; _} | Sc_rollup_execute_outbox_message_result {paid_storage_size_diff; _} | Tx_rollup_dispatch_tickets_result {paid_storage_size_diff; _} - | Transfer_ticket_result {paid_storage_size_diff; _} -> + | Transfer_ticket_result {paid_storage_size_diff; _} + | Zk_rollup_publish_result {paid_storage_size_diff; _} + | Transaction_result + (Transaction_to_zk_rollup_result {paid_storage_size_diff; _}) -> Ok paid_storage_size_diff | Sc_rollup_originate_result {size; _} -> Ok size | Zk_rollup_origination_result {storage_size; _} -> Ok storage_size @@ -445,6 +451,9 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size We need to charge for newly allocated storage (as we do for Michelson’s big map). *) Ok Z.zero + | ITransaction_result + (Transaction_to_zk_rollup_result {paid_storage_size_diff; _}) -> + Ok paid_storage_size_diff | ITransaction_result (Transaction_to_sc_rollup_result _) | IDelegation_result _ | IEvent_result _ -> Ok Z.zero) @@ -492,7 +501,8 @@ let originated_contracts_single (type kind) Ok originated_contracts | Transaction_result ( Transaction_to_tx_rollup_result _ - | Transaction_to_sc_rollup_result _ ) + | Transaction_to_sc_rollup_result _ + | Transaction_to_zk_rollup_result _ ) | Register_global_constant_result _ | Reveal_result _ | Delegation_result _ | Set_deposits_limit_result _ | Update_consensus_key_result _ | Increase_paid_storage_result _ @@ -507,7 +517,7 @@ let originated_contracts_single (type kind) | Sc_rollup_timeout_result _ | Sc_rollup_execute_outbox_message_result _ | Sc_rollup_recover_bond_result _ | Sc_rollup_dal_slot_subscribe_result _ | Zk_rollup_origination_result _ - -> + | Zk_rollup_publish_result _ -> Ok []) | Skipped _ -> error_with "Cannot know originated contracts of skipped operation" @@ -526,7 +536,8 @@ let originated_contracts_single (type kind) Ok originated_contracts | ITransaction_result ( Transaction_to_tx_rollup_result _ - | Transaction_to_sc_rollup_result _ ) + | Transaction_to_sc_rollup_result _ + | Transaction_to_zk_rollup_result _ ) | IDelegation_result _ | IEvent_result _ -> Ok []) | Skipped _ -> Ok [] (* there must be another error for this to happen *) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 5551f7de4322ff25b2391f959df07f8548c24a5d..529d0ed8306ff4664c984e1bb903654efd23f576 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -420,6 +420,8 @@ let pp_manager_operation_content (type kind) source ppf slot | Zk_rollup_origination _ -> Format.fprintf ppf "Zk rollup origination:@,From: %a" Contract.pp source + | Zk_rollup_publish _ -> + Format.fprintf ppf "Zk rollup publish:@,From: %a" Contract.pp source let pp_balance_updates ppf balance_updates = let open Receipt in @@ -657,6 +659,12 @@ let pp_transaction_result ppf = function | Transaction_to_sc_rollup_result {consumed_gas; inbox_after} -> pp_consumed_gas ppf consumed_gas ; pp_inbox_after ppf inbox_after + | Transaction_to_zk_rollup_result + {balance_updates; consumed_gas; ticket_hash; paid_storage_size_diff} -> + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates ; + Format.fprintf ppf "@,Ticket hash: %a" Ticket_hash.pp ticket_hash ; + pp_paid_storage_size_diff ppf paid_storage_size_diff let pp_operation_result ~operation_name pp_operation_result ppf = function | Skipped _ -> Format.fprintf ppf "This operation was skipped." @@ -848,6 +856,13 @@ let pp_manager_operation_contents_result ppf op_result = Format.fprintf ppf "@,Address: %a" Zk_rollup.Address.pp originated_zk_rollup ; pp_balance_updates ppf balance_updates in + let pp_zk_rollup_publish_result + (Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff}) = + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + in let manager_operation_name (type kind) (result : kind successful_manager_operation_result) = @@ -888,6 +903,7 @@ let pp_manager_operation_contents_result ppf op_result = | Dal_publish_slot_header_result _ -> "data availability slot header publishing" | Zk_rollup_origination_result _ -> "zk rollup originate" + | Zk_rollup_publish_result _ -> "zk rollup publish" in let pp_manager_operation_contents_result (type kind) ppf (result : kind successful_manager_operation_result) = @@ -932,6 +948,7 @@ let pp_manager_operation_contents_result ppf op_result = | 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 + | Zk_rollup_publish_result _ as op -> pp_zk_rollup_publish_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 e9cdbaa5e87d37d3ddb310630b3f6c5165043ce4..e82d6668f88d75be8a90714a929b9518ead9814e 100644 --- a/src/proto_alpha/lib_injector/l1_operation.ml +++ b/src/proto_alpha/lib_injector/l1_operation.ml @@ -107,6 +107,7 @@ module Manager_operation = struct | 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 + | Zk_rollup_publish _ -> zk_rollup_publish_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 dd0b6e869c4d87dba1bd765f4f0fa99458d9097f..884ed4c287a0bc0d783af89d7b374afad874903c 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -236,7 +236,14 @@ 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}; + zk_rollup = + { + enable = false; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3726 + The following constants need to be refined. *) + origination_size = 4_000; + 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 b6249dbcdaba6f1d350da00eec8f18e312379d20..b97667dbb8e11258bd0206db329b7dbb7290e5e9 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -85,6 +85,7 @@ "Zk_rollup_repr", "Zk_rollup_state_repr", "Zk_rollup_account_repr", + "Zk_rollup_ticket_repr", "Zk_rollup_operation_repr", "Bond_id_repr", @@ -171,6 +172,7 @@ "Sc_rollup_stake_storage", "Sc_rollup_refutation_storage", "Sc_rollup_storage", + "Zk_rollup_errors", "Dal_slot_storage", @@ -217,6 +219,7 @@ "Ticket_lazy_storage_diff", "Tx_rollup_parameters", + "Zk_rollup_parameters", "Ticket_token_map", "Ticket_operations_diff", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index d90c0d85630e63da899ee3f5548b57c9dc926cb1..abdb7af44a5939a814abf50aac09e02efcca8653 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -128,6 +128,8 @@ module Zk_rollup = struct module State = Zk_rollup_state_repr module Account = Zk_rollup_account_repr module Operation = Zk_rollup_operation_repr + module Ticket = Zk_rollup_ticket_repr + module Errors = Zk_rollup_errors include Zk_rollup_storage end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 8311ffd31ec2c8f2e69836e578018ff0646a9997..17e2d4147ae485b47c2aa29ead0582252d1ba447 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -820,7 +820,11 @@ module Constants : sig max_number_of_stored_cemented_commitments : int; } - type zk_rollup = {enable : bool; min_pending_to_process : int} + type zk_rollup = { + enable : bool; + origination_size : int; + min_pending_to_process : int; + } type t = { preserved_cycles : int; @@ -1791,8 +1795,6 @@ module Tx_rollup : sig val encoding : t Data_encoding.t - val deposit_entrypoint : Entrypoint.t - val originate : context -> (context * t) tzresult Lwt.t module Set : Set.S with type elt = t @@ -2351,7 +2353,11 @@ module Zk_rollup : sig nb_ops : int; } - type dynamic = {state : State.t} + type dynamic = { + state : State.t; + paid_l2_operations_storage_space : Z.t; + used_l2_operations_storage_space : Z.t; + } type t = {static : static; dynamic : dynamic} @@ -2360,9 +2366,11 @@ module Zk_rollup : sig (** This module re-exports definitions from {!Zk_rollup_operation_repr}. *) module Operation : sig + type price = {id : Ticket_hash.t; amount : Z.t} + type t = { op_code : int; - price : Ticket_hash.t * Z.t; + price : price; l1_dst : Signature.Public_key_hash.t; rollup_id : Address.t; payload : scalar array; @@ -2373,20 +2381,45 @@ module Zk_rollup : sig val to_scalar_array : t -> scalar array end + module Ticket : sig + type t = {contents : Script.expr; ty : Script.expr; ticketer : Contract.t} + + val encoding : t Data_encoding.t + 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 in_memory_size : t -> Cache_memory_helpers.sint + val originate : context -> Account.static -> init_state:State.t -> (context * Address.t * Z.t) tzresult Lwt.t + val add_to_pending : + context -> + Address.t -> + (Operation.t * Ticket_hash.t option) list -> + (context * Z.t) tzresult Lwt.t + + val assert_exist : context -> t -> context tzresult Lwt.t + val exists : context -> t -> (context * bool) tzresult Lwt.t + module Errors : sig + type error += + | Deposit_as_external + | Invalid_deposit_amount + | Invalid_deposit_ticket + | Wrong_deposit_parameters + | Ticket_payload_size_limit_exceeded of {payload_size : int; limit : int} + end + module Internal_for_tests : sig val originated_zk_rollup : Origination_nonce.Internal_for_tests.t -> t end @@ -3730,6 +3763,7 @@ module Destination : sig | Contract of Contract.t | Tx_rollup of Tx_rollup.t | Sc_rollup of Sc_rollup.t + | Zk_rollup of Zk_rollup.t val encoding : t Data_encoding.t @@ -4031,6 +4065,8 @@ module Kind : sig type zk_rollup_origination = Zk_rollup_origination_kind + type zk_rollup_publish = Zk_rollup_publish_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -4066,6 +4102,7 @@ module Kind : sig | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager end (** All the definitions below are re-exported from {!Operation_repr}. *) @@ -4317,6 +4354,11 @@ and _ manager_operation = nb_ops : int; } -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup.t; + ops : (Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list; + } + -> Kind.zk_rollup_publish manager_operation and counter = Z.t @@ -4517,6 +4559,8 @@ module Operation : sig val zk_rollup_origination_case : Kind.zk_rollup_origination Kind.manager case + val zk_rollup_publish_case : Kind.zk_rollup_publish Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -4590,6 +4634,8 @@ module Operation : sig Kind.sc_rollup_dal_slot_subscribe case val zk_rollup_origination_case : Kind.zk_rollup_origination case + + val zk_rollup_publish_case : Kind.zk_rollup_publish case end end diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index ad3cd22adb6223cf9cb75b303e6f39761393368b..54031cc3901830ea99a1740b3abe0e8a75f9b489 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -430,25 +430,6 @@ let apply_transaction_to_smart_contract ~ctxt ~source ~contract_hash ~amount in (ctxt, result, operations) ) -let ex_ticket_size : - context -> Ticket_scanner.ex_ticket -> (context * int) tzresult Lwt.t = - fun ctxt (Ex_ticket (ty, ticket)) -> - (* type *) - Script_typed_ir.ticket_t Micheline.dummy_location ty >>?= fun ty -> - Script_ir_unparser.unparse_ty ~loc:Micheline.dummy_location ctxt ty - >>?= fun (ty', ctxt) -> - let ty_nodes, ty_size = Script_typed_ir_size.node_size ty' in - let ty_size = Saturation_repr.to_int ty_size in - let ty_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:ty_nodes in - Gas.consume ctxt ty_size_cost >>?= fun ctxt -> - (* contents *) - let val_nodes, val_size = Script_typed_ir_size.value_size ty ticket in - let val_size = Saturation_repr.to_int val_size in - let val_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:val_nodes in - Gas.consume ctxt val_size_cost >>?= fun ctxt -> - (* gas *) - return (ctxt, ty_size + val_size) - let apply_transaction_to_tx_rollup ~ctxt ~parameters_ty ~parameters ~payer ~dst_rollup ~since = assert_tx_rollup_feature_enabled ctxt >>?= fun () -> @@ -462,7 +443,7 @@ let apply_transaction_to_tx_rollup ~ctxt ~parameters_ty ~parameters ~payer let Tx_rollup_parameters.{ex_ticket; l2_destination} = Tx_rollup_parameters.get_deposit_parameters parameters_ty parameters in - ex_ticket_size ctxt ex_ticket >>=? fun (ctxt, ticket_size) -> + Ticket_scanner.ex_ticket_size ctxt ex_ticket >>=? fun (ticket_size, ctxt) -> let limit = Constants.tx_rollup_max_ticket_payload_size ctxt in fail_when Compare.Int.(ticket_size > limit) @@ -680,6 +661,14 @@ let apply_internal_operation_contents : IEvent_result {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, [] ) + | Transaction_to_zk_rollup + {destination; unparsed_parameters = _; parameters_ty; parameters} -> + Zk_rollup_apply.transaction_to_zk_rollup + ~ctxt + ~parameters_ty + ~parameters + ~dst_rollup:destination + ~since:ctxt_before_op | Origination { delegate; @@ -1431,6 +1420,8 @@ let apply_manager_operation : ~circuits_info ~init_state ~nb_ops + | Zk_rollup_publish {zk_rollup; ops} -> + Zk_rollup_apply.publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops:ops type success_or_failure = Success of context | Failure @@ -1514,6 +1505,15 @@ let burn_transaction_storage_fees ctxt trr ~storage_limit ~payer = storage_limit, Transaction_to_tx_rollup_result {payload with balance_updates} ) | Transaction_to_sc_rollup_result _ -> return (ctxt, storage_limit, trr) + | Transaction_to_zk_rollup_result payload -> + let consumed = payload.paid_storage_size_diff in + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + >>=? fun (ctxt, storage_limit, storage_bus) -> + let balance_updates = storage_bus @ payload.balance_updates in + return + ( ctxt, + storage_limit, + Transaction_to_zk_rollup_result {payload with balance_updates} ) let burn_origination_storage_fees ctxt { @@ -1664,6 +1664,14 @@ let burn_manager_storage_fees : Zk_rollup_origination_result {payload with balance_updates} in return (ctxt, storage_limit, result) + | Zk_rollup_publish_result payload -> + let consumed = payload.paid_storage_size_diff in + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + >|=? fun (ctxt, storage_limit, storage_bus) -> + let balance_updates = storage_bus @ payload.balance_updates in + ( ctxt, + storage_limit, + Zk_rollup_publish_result {payload with balance_updates} ) (** [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_internal_results.ml b/src/proto_alpha/lib_protocol/apply_internal_results.ml index 218e0ec095055def988a97f925f0d39822e19ae8..7986c5877950a64feb6a33e7b307db174412942f 100644 --- a/src/proto_alpha/lib_protocol/apply_internal_results.ml +++ b/src/proto_alpha/lib_protocol/apply_internal_results.ml @@ -93,7 +93,7 @@ let internal_operation (type kind) destination = Tx_rollup destination; (* Dummy amount used for the external untyped view of internal transactions *) amount = Tez.zero; - entrypoint = Tx_rollup.deposit_entrypoint; + entrypoint = Entrypoint.deposit; parameters = Script.lazy_expr unparsed_parameters; } | Transaction_to_sc_rollup {destination; entrypoint; unparsed_parameters; _} @@ -106,6 +106,14 @@ let internal_operation (type kind) parameters = Script.lazy_expr unparsed_parameters; } | Event {ty; tag; unparsed_data} -> Event {ty; tag; payload = unparsed_data} + | Transaction_to_zk_rollup {destination; unparsed_parameters; _} -> + Transaction + { + destination = Zk_rollup destination; + amount = Tez.zero; + entrypoint = Entrypoint.deposit; + parameters = Script.lazy_expr unparsed_parameters; + } | Origination {delegate; code; unparsed_storage; credit; _} -> let script = { @@ -145,6 +153,12 @@ type successful_transaction_result = consumed_gas : Gas.Arith.fp; inbox_after : Sc_rollup.Inbox.t; } + | Transaction_to_zk_rollup_result of { + ticket_hash : Ticket_hash.t; + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } type successful_origination_result = { lazy_storage_diff : Lazy_storage.diffs option; diff --git a/src/proto_alpha/lib_protocol/apply_internal_results.mli b/src/proto_alpha/lib_protocol/apply_internal_results.mli index 10e33aad5aff10ad7dfeff39e18c64119edc2609..92754cceb50a22cf00cfec1914290cd1f36229b2 100644 --- a/src/proto_alpha/lib_protocol/apply_internal_results.mli +++ b/src/proto_alpha/lib_protocol/apply_internal_results.mli @@ -98,6 +98,12 @@ type successful_transaction_result = consumed_gas : Gas.Arith.fp; inbox_after : Sc_rollup.Inbox.t; } + | Transaction_to_zk_rollup_result of { + ticket_hash : Ticket_hash.t; + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } (** Result of applying an internal origination. *) type successful_origination_result = { diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index d003a9d1ea94a1e870cc85a1b4c288dccc99ef09..346b542c012daef2ef0c84fa9df10ef34b11f9a4 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -187,6 +187,12 @@ type _ successful_manager_operation_result = storage_size : Z.t; } -> Kind.zk_rollup_origination successful_manager_operation_result + | Zk_rollup_publish_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_publish successful_manager_operation_result let migration_origination_result_to_successful_manager_operation_result ({ @@ -802,6 +808,28 @@ module Manager_result = struct Zk_rollup_origination_result {balance_updates; originated_zk_rollup; consumed_gas; storage_size}) + let zk_rollup_publish_case = + make + ~op_case:Operation.Encoding.Manager_operations.zk_rollup_publish_case + ~encoding: + Data_encoding.( + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "size" z)) + ~select:(function + | Successful_manager_result (Zk_rollup_publish_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Zk_rollup_publish_manager_kind + ~proj:(function + | Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff} -> + (balance_updates, consumed_gas, paid_storage_size_diff)) + ~inj:(fun (balance_updates, consumed_gas, paid_storage_size_diff) -> + Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff}) + let sc_rollup_originate_case = make ~op_case:Operation.Encoding.Manager_operations.sc_rollup_originate_case @@ -1206,6 +1234,9 @@ let equal_manager_kind : Kind.Zk_rollup_origination_manager_kind ) -> Some Eq | Kind.Zk_rollup_origination_manager_kind, _ -> None + | Kind.Zk_rollup_publish_manager_kind, Kind.Zk_rollup_publish_manager_kind -> + Some Eq + | Kind.Zk_rollup_publish_manager_kind, _ -> None module Encoding = struct type 'kind case = @@ -1876,6 +1907,17 @@ module Encoding = struct res ) -> Some (op, res) | _ -> None) + + let zk_rollup_publish_case = + make_manager_case + Operation.Encoding.zk_rollup_publish_case + Manager_result.zk_rollup_publish_case + (function + | Contents_and_result + ((Manager_operation {operation = Zk_rollup_publish _; _} as op), res) + -> + Some (op, res) + | _ -> None) end let contents_result_encoding = @@ -1937,6 +1979,7 @@ let contents_result_encoding = make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; make zk_rollup_origination_case; + make zk_rollup_publish_case; ] let contents_and_result_encoding = @@ -2003,6 +2046,7 @@ let contents_and_result_encoding = make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; make zk_rollup_origination_case; + make zk_rollup_publish_case; ] type 'kind contents_result_list = @@ -2884,6 +2928,31 @@ let kind_equal : } ) -> Some Eq | Manager_operation {operation = Zk_rollup_origination _; _}, _ -> None + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + {operation_result = Applied (Zk_rollup_publish_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + {operation_result = Backtracked (Zk_rollup_publish_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Zk_rollup_publish_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Zk_rollup_publish_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Zk_rollup_publish _; _}, _ -> 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 f60d87231dc69389580b114e2ae612c200ba6f4f..b468b0bae19ac3a71b48b2a44cd2e526dd892107 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -292,6 +292,12 @@ and _ successful_manager_operation_result = storage_size : Z.t; } -> Kind.zk_rollup_origination successful_manager_operation_result + | Zk_rollup_publish_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_publish 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 59d1c6c1db164fa048bfae9b77d0bf50da9ac76c..7f009a5d9a47ff8807d4bc18ba3abf6505ca871b 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -127,7 +127,11 @@ type sc_rollup = { max_number_of_stored_cemented_commitments : int; } -type zk_rollup = {enable : bool; min_pending_to_process : int} +type zk_rollup = { + enable : bool; + origination_size : int; + min_pending_to_process : int; +} type t = { preserved_cycles : int; @@ -310,15 +314,19 @@ let sc_rollup_encoding = 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) -> + (fun ({enable; origination_size; min_pending_to_process} : zk_rollup) -> + (enable, origination_size, min_pending_to_process)) + (fun ( zk_rollup_enable, + zk_rollup_origination_size, + zk_rollup_min_pending_to_process ) -> { enable = zk_rollup_enable; + origination_size = zk_rollup_origination_size; min_pending_to_process = zk_rollup_min_pending_to_process; }) - (obj2 + (obj3 (req "zk_rollup_enable" bool) + (req "zk_rollup_origination_size" int31) (req "zk_rollup_min_pending_to_process" int31)) let encoding = diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index ded965c7a765447d55f4837de886a6b79116f47e..db5c1c5ab07ab668b2b8216d23581e6b9b7e40ca 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -128,6 +128,7 @@ type sc_rollup = { type zk_rollup = { enable : bool; + origination_size : int; (* 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], diff --git a/src/proto_alpha/lib_protocol/constants_storage.ml b/src/proto_alpha/lib_protocol/constants_storage.ml index 3c9a5783ca06ca3177b8062b47653da8a18098c3..df29f10c945c13b9235fcfcf7df704f2e3e25f6e 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.ml +++ b/src/proto_alpha/lib_protocol/constants_storage.ml @@ -285,3 +285,7 @@ let zk_rollup_enable c = let zk_rollup_min_pending_to_process c = let zk_rollup = Raw_context.zk_rollup c in zk_rollup.min_pending_to_process + +let zk_rollup_origination_size c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.origination_size diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index 6e1ddc8819c6964b03deee98e05f940672c42350..6418bb12893546b16f9140346e1e0340f4002a04 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -165,3 +165,5 @@ 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 + +val zk_rollup_origination_size : Raw_context.t -> int diff --git a/src/proto_alpha/lib_protocol/destination_repr.ml b/src/proto_alpha/lib_protocol/destination_repr.ml index 49e73f1c0d01e6ffcecb8b29e735f2259c6bc60b..96cf0f862b1a4b42b1e163f0db9790f6667f6222 100644 --- a/src/proto_alpha/lib_protocol/destination_repr.ml +++ b/src/proto_alpha/lib_protocol/destination_repr.ml @@ -29,6 +29,8 @@ type t = | Contract of Contract_repr.t | Tx_rollup of Tx_rollup_repr.t | Sc_rollup of Sc_rollup_repr.t + | Zk_rollup of Zk_rollup_repr.t + (* If you add more cases to this type, please update the [test_compare_destination] test in [test/unit/test_destination_repr.ml] to ensure that the compare @@ -43,6 +45,7 @@ include Compare.Make (struct | Contract k1, Contract k2 -> Contract_repr.compare k1 k2 | Tx_rollup k1, Tx_rollup k2 -> Tx_rollup_repr.compare k1 k2 | Sc_rollup k1, Sc_rollup k2 -> Sc_rollup_repr.Address.compare k1 k2 + | Zk_rollup k1, Zk_rollup k2 -> Zk_rollup_repr.Address.compare k1 k2 (* This function is used by the Michelson interpreter to compare addresses. It is of significant importance to remember that in Michelson, address comparison is used to distinguish between @@ -54,12 +57,15 @@ include Compare.Make (struct | _, Contract _ -> 1 | Tx_rollup _, _ -> -1 | _, Tx_rollup _ -> 1 + | Sc_rollup _, _ -> -1 + | _, Sc_rollup _ -> 1 end) let to_b58check = function | Contract k -> Contract_repr.to_b58check k | Tx_rollup k -> Tx_rollup_repr.to_b58check k | Sc_rollup k -> Sc_rollup_repr.Address.to_b58check k + | Zk_rollup k -> Zk_rollup_repr.Address.to_b58check k type error += Invalid_destination_b58check of string @@ -76,14 +82,15 @@ let () = (fun x -> Invalid_destination_b58check x) let of_b58data data = - match Contract_repr.of_b58data data with - | Some c -> Some (Contract c) - | None -> ( - match Tx_rollup_repr.of_b58data data with - | Some tx_rollup -> Some (Tx_rollup tx_rollup) - | None -> - Sc_rollup_repr.Address.of_b58data data - |> Option.map (fun sc_rollup -> Sc_rollup sc_rollup)) + let decode_on_none decode wrap = function + | Some x -> Some x + | None -> Option.map wrap @@ decode data + in + None + |> decode_on_none Contract_repr.of_b58data (fun c -> Contract c) + |> decode_on_none Tx_rollup_repr.of_b58data (fun t -> Tx_rollup t) + |> decode_on_none Sc_rollup_repr.Address.of_b58data (fun s -> Sc_rollup s) + |> decode_on_none Zk_rollup_repr.Address.of_b58data (fun z -> Zk_rollup z) let of_b58check_opt s = Option.bind (Base58.decode s) of_b58data @@ -122,6 +129,12 @@ let encoding = ~title:"Sc_rollup" (function Sc_rollup k -> Some k | _ -> None) (fun k -> Sc_rollup k); + case + (Tag 4) + (Fixed.add_padding Zk_rollup_repr.Address.encoding 1) + ~title:"Zk_rollup" + (function Zk_rollup k -> Some k | _ -> None) + (fun k -> Zk_rollup k); ])) ~json: (conv @@ -139,6 +152,7 @@ let pp : Format.formatter -> t -> unit = | Contract k -> Contract_repr.pp fmt k | Tx_rollup k -> Tx_rollup_repr.pp fmt k | Sc_rollup k -> Sc_rollup_repr.pp fmt k + | Zk_rollup k -> Zk_rollup_repr.Address.pp fmt k let in_memory_size = let open Cache_memory_helpers in @@ -146,3 +160,4 @@ let in_memory_size = | Contract k -> h1w +! Contract_repr.in_memory_size k | Tx_rollup k -> h1w +! Tx_rollup_repr.in_memory_size k | Sc_rollup k -> h1w +! Sc_rollup_repr.in_memory_size k + | Zk_rollup k -> h1w +! Zk_rollup_repr.in_memory_size k diff --git a/src/proto_alpha/lib_protocol/destination_repr.mli b/src/proto_alpha/lib_protocol/destination_repr.mli index 2b0c3e57f0c58d1cc48db08b5d0718367c28badc..2bb07891b4fd47673b117d2756d071c946249189 100644 --- a/src/proto_alpha/lib_protocol/destination_repr.mli +++ b/src/proto_alpha/lib_protocol/destination_repr.mli @@ -45,6 +45,7 @@ type t = | Contract of Contract_repr.t | Tx_rollup of Tx_rollup_repr.t | Sc_rollup of Sc_rollup_repr.t + | Zk_rollup of Zk_rollup_repr.t include Compare.S with type t := t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index c8a8b9ecab2732bc7cc099dc97a806aab7f02350..e62bcc544f93eb81edfff1de0a9b9914d949bd89 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -112,6 +112,7 @@ Zk_rollup_repr Zk_rollup_state_repr Zk_rollup_account_repr + Zk_rollup_ticket_repr Zk_rollup_operation_repr Bond_id_repr Vote_repr @@ -189,6 +190,7 @@ Sc_rollup_stake_storage Sc_rollup_refutation_storage Sc_rollup_storage + Zk_rollup_errors Dal_slot_storage Alpha_context Script_string @@ -230,6 +232,7 @@ Ticket_balance_key Ticket_lazy_storage_diff Tx_rollup_parameters + Zk_rollup_parameters Ticket_token_map Ticket_operations_diff Ticket_accounting @@ -373,6 +376,7 @@ 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_ticket_repr.ml zk_rollup_ticket_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 @@ -451,6 +455,7 @@ sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + zk_rollup_errors.ml dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli @@ -492,6 +497,7 @@ ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli ticket_token_map.ml ticket_token_map.mli ticket_operations_diff.ml ticket_operations_diff.mli ticket_accounting.ml ticket_accounting.mli @@ -615,6 +621,7 @@ 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_ticket_repr.ml zk_rollup_ticket_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 @@ -693,6 +700,7 @@ sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + zk_rollup_errors.ml dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli @@ -734,6 +742,7 @@ ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli ticket_token_map.ml ticket_token_map.mli ticket_operations_diff.ml ticket_operations_diff.mli ticket_accounting.ml ticket_accounting.mli @@ -862,6 +871,7 @@ 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_ticket_repr.ml zk_rollup_ticket_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 @@ -940,6 +950,7 @@ sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + zk_rollup_errors.ml dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli @@ -981,6 +992,7 @@ ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli ticket_token_map.ml ticket_token_map.mli ticket_operations_diff.ml ticket_operations_diff.mli ticket_accounting.ml ticket_accounting.mli diff --git a/src/proto_alpha/lib_protocol/entrypoint_repr.ml b/src/proto_alpha/lib_protocol/entrypoint_repr.ml index a59dbccc0f4b22eb017607c20a90e94ebf744ca5..03662185f7a6f19d15a15fe2a9dfafa93808ba97 100644 --- a/src/proto_alpha/lib_protocol/entrypoint_repr.ml +++ b/src/proto_alpha/lib_protocol/entrypoint_repr.ml @@ -157,6 +157,10 @@ let set_delegate = of_string_strict_exn "set_delegate" let remove_delegate = of_string_strict_exn "remove_delegate" +let deposit = of_string_strict_exn "deposit" + +let is_deposit = ( = ) deposit + let is_root = ( = ) root let to_non_empty_string (name : t) = (name :> Non_empty_string.t) @@ -207,6 +211,7 @@ let smart_encoding = builtin_case 2 do_; builtin_case 3 set_delegate; builtin_case 4 remove_delegate; + builtin_case 5 deposit; case (Tag 255) ~title:"named" diff --git a/src/proto_alpha/lib_protocol/entrypoint_repr.mli b/src/proto_alpha/lib_protocol/entrypoint_repr.mli index 8a31b3b58bc1e1c995352a92b49a0444df9bf2d4..cef8b2a63f21b930d7da054221406ddf297f2d5b 100644 --- a/src/proto_alpha/lib_protocol/entrypoint_repr.mli +++ b/src/proto_alpha/lib_protocol/entrypoint_repr.mli @@ -53,6 +53,12 @@ val set_delegate : t (** Entrypoint "remove_delegate" *) val remove_delegate : t +(** Deposit entrypoint "deposit" *) +val deposit : t + +(** Checks whether an entrypoint is the deposit entrypoint *) +val is_deposit : t -> bool + (** Converts an annot to an entrypoint. Returns an error if the string is too long or is "default". *) val of_annot_strict : diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index e66e2a17f33cb6324bea6fe2ff8a04d43d564d22..02bd2d7fda8b5459c7aaa8da1a32a3105f284380 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -125,6 +125,8 @@ module Kind = struct type zk_rollup_origination = Zk_rollup_origination_kind + type zk_rollup_publish = Zk_rollup_publish_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -160,6 +162,7 @@ module Kind = struct | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager end type 'a consensus_operation_type = @@ -481,6 +484,11 @@ and _ manager_operation = nb_ops : int; } -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup_repr.t; + ops : (Zk_rollup_operation_repr.t * Zk_rollup_ticket_repr.t option) list; + } + -> Kind.zk_rollup_publish manager_operation and counter = Z.t @@ -518,6 +526,7 @@ let manager_kind : type kind. kind manager_operation -> kind Kind.manager = | Sc_rollup_dal_slot_subscribe _ -> Kind.Sc_rollup_dal_slot_subscribe_manager_kind | Zk_rollup_origination _ -> Kind.Zk_rollup_origination_manager_kind + | Zk_rollup_publish _ -> Kind.Zk_rollup_publish_manager_kind type packed_manager_operation = | Manager : 'kind manager_operation -> packed_manager_operation @@ -620,6 +629,8 @@ let zk_rollup_operation_tag_offset = 250 let zk_rollup_operation_create_tag = zk_rollup_operation_tag_offset + 0 +let zk_rollup_operation_publish_tag = zk_rollup_operation_tag_offset + 1 + module Encoding = struct open Data_encoding @@ -1081,6 +1092,27 @@ module Encoding = struct {public_parameters; circuits_info; init_state; nb_ops}); } + let zk_rollup_publish_case = + MCase + { + tag = zk_rollup_operation_publish_tag; + name = "zk_rollup_publish"; + encoding = + obj2 + (req "zk_rollup" Zk_rollup_repr.Address.encoding) + (req "op" + @@ Data_encoding.list + (tup2 + Zk_rollup_operation_repr.encoding + (option Zk_rollup_ticket_repr.encoding))); + select = + (function + | Manager (Zk_rollup_publish _ as op) -> Some op | _ -> None); + proj = + (function Zk_rollup_publish {zk_rollup; ops} -> (zk_rollup, ops)); + inj = (fun (zk_rollup, ops) -> Zk_rollup_publish {zk_rollup; ops}); + } + let string_to_bytes_encoding = Data_encoding.conv Bytes.of_string Bytes.to_string Data_encoding.bytes @@ -1738,6 +1770,11 @@ module Encoding = struct zk_rollup_operation_create_tag Manager_operations.zk_rollup_origination_case + let zk_rollup_publish_case = + make_manager_case + zk_rollup_operation_publish_tag + Manager_operations.zk_rollup_publish_case + let contents_encoding = let make (Case {tag; name; encoding; select; proj; inj}) = case @@ -1791,6 +1828,7 @@ module Encoding = struct make sc_rollup_recover_bond_case; make sc_rollup_dal_slot_subscribe_case; make zk_rollup_origination_case; + make zk_rollup_publish_case; ] let contents_list_encoding = @@ -2052,6 +2090,8 @@ let equal_manager_operation_kind : | Sc_rollup_dal_slot_subscribe _, _ -> None | Zk_rollup_origination _, Zk_rollup_origination _ -> Some Eq | Zk_rollup_origination _, _ -> None + | Zk_rollup_publish _, Zk_rollup_publish _ -> Some Eq + | Zk_rollup_publish _, _ -> 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 168184395c05305e1b6e20e4fb60e7440eb6de51..5b17ce35aa13e34afbd8fa80c8b5a876a2a47a0d 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -50,6 +50,7 @@ - tx rollup reveal withdrawals - smart contract rollup origination - zk rollup origination + - zk rollup publish Each of them can be encoded as raw bytes. Operations are distinguished at type level using phantom type parameters. [packed_operation] type allows @@ -155,6 +156,8 @@ module Kind : sig type zk_rollup_origination = Zk_rollup_origination_kind + type zk_rollup_publish = Zk_rollup_publish_kind + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager @@ -190,6 +193,7 @@ module Kind : sig | Sc_rollup_dal_slot_subscribe_manager_kind : sc_rollup_dal_slot_subscribe manager | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager end type 'a consensus_operation_type = @@ -572,6 +576,12 @@ and _ manager_operation = nb_ops : int; } -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup_repr.t; + ops : (Zk_rollup_operation_repr.t * Zk_rollup_ticket_repr.t option) list; + (* See {!Zk_rollup_apply} *) + } + -> Kind.zk_rollup_publish manager_operation (** Counters are used as anti-replay protection mechanism in manager operations: each manager account stores a counter and @@ -827,6 +837,8 @@ module Encoding : sig val zk_rollup_origination_case : Kind.zk_rollup_origination Kind.manager case + val zk_rollup_publish_case : Kind.zk_rollup_publish Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -899,5 +911,7 @@ module Encoding : sig Kind.sc_rollup_dal_slot_subscribe case val zk_rollup_origination_case : Kind.zk_rollup_origination case + + val zk_rollup_publish_case : Kind.zk_rollup_publish case end end diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 59cecc74b4964e51d8b8bdb34f947d4baf209e23..ec772df2d09770feed4ff248633a0991cd8111ce 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -1016,7 +1016,12 @@ let prepare_first_block ~level ~timestamp ctxt = } in let zk_rollup = - Constants_parametric_repr.{enable = false; min_pending_to_process = 10} + Constants_parametric_repr. + { + enable = false; + origination_size = 4_000; + min_pending_to_process = 10; + } in let constants = Constants_parametric_repr. diff --git a/src/proto_alpha/lib_protocol/script_interpreter.ml b/src/proto_alpha/lib_protocol/script_interpreter.ml index 0e98a095f66db2e014a6cac20242e49b461fb5f1..cac3f9933346436cc9f93949a8599116a3c99c66 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter.ml @@ -523,7 +523,7 @@ and iview : type a b c d e f i o. (a, b, c, d, e, f, i, o) iview_type = in let legacy = Script_ir_translator_config.make ~legacy:true () in match addr.destination with - | Contract (Implicit _) | Tx_rollup _ | Sc_rollup _ -> + | Contract (Implicit _) | Tx_rollup _ | Sc_rollup _ | Zk_rollup _ -> (return_none [@ocaml.tailcall]) ctxt | Contract (Originated contract_hash as c) -> ( Contract.get_script ctxt contract_hash >>=? fun (ctxt, script_opt) -> diff --git a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml index ab0c2464303a201100d862a2dbde11d19ce67729..5cbaa5d9ad314325e2a65bebf7be5745bf7f0bd4 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml @@ -592,6 +592,20 @@ let emit_event (type t tc) (ctxt, sc) gas ~(event_type : (t, tc) ty) let gas, ctxt = local_gas_counter_and_outdated_context ctxt in return (res, ctxt, gas) +let make_transaction_to_zk_rollup (type t) ctxt ~destination ~amount + ~(parameters_ty : ((t ticket, bytes) pair, _) ty) ~parameters = + error_unless Tez.(amount = zero) Rollup_invalid_transaction_amount + >>?= fun () -> + unparse_data ctxt Optimized parameters_ty parameters + >>=? fun (unparsed_parameters, ctxt) -> + Lwt.return + ( Gas.consume ctxt (Script.strip_locations_cost unparsed_parameters) + >|? fun ctxt -> + let unparsed_parameters = Micheline.strip_locations unparsed_parameters in + ( Transaction_to_zk_rollup + {destination; parameters_ty; parameters; unparsed_parameters}, + ctxt ) ) + (* [transfer (ctxt, sc) gas tez parameters_ty parameters destination entrypoint] creates an operation that transfers an amount of [tez] to a destination and an entrypoint instantiated with argument [parameters] of type @@ -654,6 +668,14 @@ let transfer (type t) (ctxt, sc) gas amount location ~entrypoint ~parameters_ty ~parameters + >|=? fun (operation, ctxt) -> (operation, None, ctxt) + | Typed_zk_rollup {arg_ty = parameters_ty; zk_rollup = destination} -> + make_transaction_to_zk_rollup + ctxt + ~destination + ~amount + ~parameters_ty + ~parameters >|=? fun (operation, ctxt) -> (operation, None, ctxt)) >>=? fun (operation, lazy_storage_diff, ctxt) -> fresh_internal_nonce ctxt >>?= fun (ctxt, nonce) -> diff --git a/src/proto_alpha/lib_protocol/script_ir_translator.ml b/src/proto_alpha/lib_protocol/script_ir_translator.ml index ea3d29b5e7e00f0462321073f725db54d4670c1d..2c0d1eb85076f5355bdb4aca59672de93bf4d2dc 100644 --- a/src/proto_alpha/lib_protocol/script_ir_translator.ml +++ b/src/proto_alpha/lib_protocol/script_ir_translator.ml @@ -1628,6 +1628,8 @@ let parse_address ctxt : Script.node -> (address * context) tzresult = error @@ Tx_rollup_addresses_disabled loc | Destination.Sc_rollup _ when not (Constants.sc_rollup_enable ctxt) -> error @@ Sc_rollup_disabled loc + | Destination.Zk_rollup _ when not (Constants.zk_rollup_enable ctxt) -> + error @@ Zk_rollup_disabled loc | _ -> Ok ({destination; entrypoint}, ctxt) in function @@ -2117,7 +2119,7 @@ let rec parse_data : | Some amount -> ( match destination with | Contract ticketer -> return ({ticketer; contents; amount}, ctxt) - | Tx_rollup _ | Sc_rollup _ -> + | Tx_rollup _ | Sc_rollup _ | Zk_rollup _ -> fail (Unexpected_ticket_owner destination)) | None -> traced_fail Forbidden_zero_ticket_quantity else traced_fail (Unexpected_forged_value (location expr)) @@ -4552,7 +4554,7 @@ and parse_contract : Typed_originated {arg_ty; contract_hash; entrypoint} )) )) | Tx_rollup tx_rollup -> Tx_rollup_state.assert_exist ctxt tx_rollup >|=? fun ctxt -> - if Entrypoint.(entrypoint = Tx_rollup.deposit_entrypoint) then + if Entrypoint.(is_deposit entrypoint) then (* /!\ This pattern matching needs to remain in sync with [parse_tx_rollup_deposit_parameters]. *) match arg with @@ -4565,6 +4567,19 @@ and parse_contract : error ctxt (fun loc -> Tx_rollup_bad_deposit_parameter (loc, serialize_ty_for_error arg)) else error ctxt (fun _loc -> No_such_entrypoint entrypoint) + | Zk_rollup zk_rollup -> + Zk_rollup.assert_exist ctxt zk_rollup >|=? fun ctxt -> + if Entrypoint.(is_deposit entrypoint) then + match arg with + | Pair_t (Ticket_t (_, _), Bytes_t, _, _) -> + ( ctxt, + ok + @@ (Typed_zk_rollup {arg_ty = arg; zk_rollup} + : arg typed_contract) ) + | _ -> + error ctxt (fun loc -> + Zk_rollup_bad_deposit_parameter (loc, serialize_ty_for_error arg)) + else error ctxt (fun _loc -> No_such_entrypoint entrypoint) | Sc_rollup sc_rollup -> Sc_rollup.parameters_type ctxt sc_rollup >>=? fun (parameters_type, ctxt) -> diff --git a/src/proto_alpha/lib_protocol/script_tc_errors.ml b/src/proto_alpha/lib_protocol/script_tc_errors.ml index ba465e11c33312fa15724f5320d4817b51e81c92..64be6905ed23723e244af9327587a69e6fd9b78e 100644 --- a/src/proto_alpha/lib_protocol/script_tc_errors.ml +++ b/src/proto_alpha/lib_protocol/script_tc_errors.ml @@ -82,6 +82,12 @@ type error += Tx_rollup_addresses_disabled of Script.location type error += Sc_rollup_disabled of Script.location +(* Zero Knowledge rollup errors *) + +type error += Zk_rollup_disabled of Script.location + +type error += Zk_rollup_bad_deposit_parameter of Script.location * Script.expr + (* Instruction typing errors *) type error += Fail_not_in_tail_position of Script.location diff --git a/src/proto_alpha/lib_protocol/script_typed_ir.ml b/src/proto_alpha/lib_protocol/script_typed_ir.ml index 8b69ca75bf42b52a1d19844d001089cfdde404cc..3f4cfecff9152e138323b9eb3912e0aec4a13a38 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir.ml +++ b/src/proto_alpha/lib_protocol/script_typed_ir.ml @@ -1139,6 +1139,11 @@ and 'arg typed_contract = entrypoint : Entrypoint.t; } -> 'arg typed_contract + | Typed_zk_rollup : { + arg_ty : (('a ticket, bytes) pair, _) ty; + zk_rollup : Zk_rollup.t; + } + -> ('a ticket, bytes) pair typed_contract and (_, _, _, _) continuation = | KNil : ('r, 'f, 'r, 'f) continuation @@ -1398,6 +1403,13 @@ and 'kind internal_operation_contents = unparsed_data : Script.expr; } -> Kind.event internal_operation_contents + | Transaction_to_zk_rollup : { + destination : Zk_rollup.t; + parameters_ty : (('a ticket, bytes) pair, _) ty; + parameters : ('a ticket, bytes) pair; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents | Origination : { delegate : Signature.Public_key_hash.t option; code : Script.expr; @@ -1453,6 +1465,7 @@ let manager_kind : | Transaction_to_smart_contract _ -> Kind.Transaction_manager_kind | Transaction_to_tx_rollup _ -> Kind.Transaction_manager_kind | Transaction_to_sc_rollup _ -> Kind.Transaction_manager_kind + | Transaction_to_zk_rollup _ -> Kind.Transaction_manager_kind | Event _ -> Kind.Event_manager_kind | Origination _ -> Kind.Origination_manager_kind | Delegation _ -> Kind.Delegation_manager_kind @@ -2174,18 +2187,21 @@ module Typed_contract = struct Destination.Contract (Originated contract_hash) | Typed_tx_rollup {tx_rollup; _} -> Destination.Tx_rollup tx_rollup | Typed_sc_rollup {sc_rollup; _} -> Destination.Sc_rollup sc_rollup + | Typed_zk_rollup {zk_rollup; _} -> Destination.Zk_rollup zk_rollup let arg_ty : type a. a typed_contract -> a ty_ex_c = function | Typed_implicit _ -> (Ty_ex_c Unit_t : a ty_ex_c) | Typed_originated {arg_ty; _} -> Ty_ex_c arg_ty | Typed_tx_rollup {arg_ty; _} -> Ty_ex_c arg_ty | Typed_sc_rollup {arg_ty; _} -> Ty_ex_c arg_ty + | Typed_zk_rollup {arg_ty; _} -> Ty_ex_c arg_ty let entrypoint : type a. a typed_contract -> Entrypoint.t = function | Typed_implicit _ -> Entrypoint.default - | Typed_tx_rollup _ -> Tx_rollup.deposit_entrypoint + | Typed_tx_rollup _ -> Entrypoint.deposit | Typed_originated {entrypoint; _} | Typed_sc_rollup {entrypoint; _} -> entrypoint + | Typed_zk_rollup _ -> Entrypoint.deposit module Internal_for_tests = struct let typed_exn : @@ -2207,5 +2223,9 @@ module Typed_contract = struct tx_rollup_l2_address)" | Sc_rollup sc_rollup, _ -> Typed_sc_rollup {arg_ty; sc_rollup; entrypoint} + | Zk_rollup zk_rollup, Pair_t (Ticket_t _, Bytes_t, _, _) -> + (Typed_zk_rollup {arg_ty; zk_rollup} : a typed_contract) + | Zk_rollup _, _ -> + invalid_arg "ZK rollups expect type (pair (ticket _) bytes)" end end diff --git a/src/proto_alpha/lib_protocol/script_typed_ir.mli b/src/proto_alpha/lib_protocol/script_typed_ir.mli index 7aa4e2b66084c3652276f6467122a320123a886b..131ab84402e2904b8481fef6de3e1076f9535f96 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir.mli +++ b/src/proto_alpha/lib_protocol/script_typed_ir.mli @@ -1140,6 +1140,11 @@ and 'arg typed_contract = entrypoint : Entrypoint.t; } -> 'arg typed_contract + | Typed_zk_rollup : { + arg_ty : (('a ticket, bytes) pair, _) ty; + zk_rollup : Zk_rollup.t; + } + -> ('a ticket, bytes) pair typed_contract (* @@ -1534,6 +1539,13 @@ and 'kind internal_operation_contents = unparsed_data : Script.expr; } -> Kind.event internal_operation_contents + | Transaction_to_zk_rollup : { + destination : Zk_rollup.t; + parameters_ty : (('a ticket, bytes) pair, _) ty; + parameters : ('a ticket, bytes) pair; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents | Origination : { delegate : Signature.Public_key_hash.t option; code : Script.expr; diff --git a/src/proto_alpha/lib_protocol/script_typed_ir_size.ml b/src/proto_alpha/lib_protocol/script_typed_ir_size.ml index 7f9d0b7ad0d3146ab1e2b0986f9f1546afa564c2..46f3626c06eae0529d01a70e16bdd95af53db7a6 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir_size.ml +++ b/src/proto_alpha/lib_protocol/script_typed_ir_size.ml @@ -203,6 +203,8 @@ let contract_size : type t. t typed_contract -> nodes_and_size = function (h3w +! Sc_rollup.in_memory_size sc_rollup +! Entrypoint.in_memory_size entrypoint) + | Typed_zk_rollup {arg_ty; zk_rollup} -> + ret_adding (ty_size arg_ty) (h2w +! Zk_rollup.in_memory_size zk_rollup) let sapling_state_size {Sapling.id; diff; memo_size} = h3w diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index f5de31e4900b501ee9754ac987dd31d0ff1ffe43..9319e69656cc35efc08d90ba46c7d646cbe391e4 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -855,11 +855,12 @@ let bake_n_with_all_balance_updates ?(baking_mode = Application) ?policy | Sc_rollup_execute_outbox_message_result _ | Sc_rollup_recover_bond_result _ | Sc_rollup_dal_slot_subscribe_result _ - | Zk_rollup_origination_result _ -> + | Zk_rollup_origination_result _ | Zk_rollup_publish_result _ -> balance_updates_rev | Transaction_result ( Transaction_to_contract_result {balance_updates; _} - | Transaction_to_tx_rollup_result {balance_updates; _} ) + | Transaction_to_tx_rollup_result {balance_updates; _} + | Transaction_to_zk_rollup_result {balance_updates; _} ) | Origination_result {balance_updates; _} | Register_global_constant_result {balance_updates; _} | Increase_paid_storage_result {balance_updates; _} -> @@ -908,7 +909,8 @@ 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 _) -> + | Successful_manager_result (Zk_rollup_origination_result _) + | Successful_manager_result (Zk_rollup_publish_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/dummy_zk_rollup.ml b/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml index cb976864a1c7824480b434826710c37226caea2d..070d69de6c603d06ab5eb31d640a0fbf9ffc251d 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dummy_zk_rollup.ml @@ -437,12 +437,12 @@ end = struct { op_code = 0; price = - (let ticket_hash = + (let id = Data_encoding.Binary.of_bytes_exn Ticket_hash.encoding dummy_ticket_hash in - (ticket_hash, Z.zero)); + {id; amount = Z.zero}); l1_dst = Data_encoding.Binary.of_bytes_exn Signature.Public_key_hash.encoding diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 5415b242697f8a14f50b209a424739ad2a2fbbd7..e2d6f927d5120f742afc1f535ad961b0d5ca3673 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -1005,3 +1005,18 @@ let drain_delegate ctxt ~consensus_key ~delegate ~destination = in Context.Contract.manager ctxt (Contract.Implicit consensus_key) >|=? fun account -> sign account.sk ctxt (Contents_list contents) + +let zk_rollup_publish ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) ~zk_rollup ~ops = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Zk_rollup_publish {zk_rollup; ops}) + >>=? fun to_sign_op -> + Context.Contract.manager ctxt src >|=? fun account -> + sign account.sk ctxt to_sign_op diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index a52e005b9df498d3d9c213cc72fe4fca5e78961f..3a3fb74885974be8a9f82b5f6fdbde278a2a5fdd 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -734,3 +734,17 @@ val drain_delegate : delegate:Signature.Public_key_hash.t -> destination:Signature.Public_key_hash.t -> packed_operation tzresult Lwt.t + +(** [zk_rollup_publish ctxt source ~zk_rollup ~op] tries to add an operation + to the pending list of a ZK Rollup. *) +val zk_rollup_publish : + ?force_reveal:bool -> + ?counter:Z.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:counter -> + Context.t -> + Contract.t -> + zk_rollup:Zk_rollup.t -> + ops:(Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list -> + Operation.packed tzresult Lwt.t 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 index 77125bdc3b68c3b055d2441021875647cb01c231..0f8eece01f0ae15968fa4a54ffd1e63029395eaf 100644 --- 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 @@ -35,6 +35,7 @@ open Protocol open Alpha_context open Lwt_result_syntax +open Error_monad_operators exception Zk_rollup_test_error of string @@ -119,8 +120,11 @@ let context_init = (* Check that the expected origination fees are paid. *) let test_origination_fees () = let* ctxt, contracts = context_init 1 in + let* constants = Context.get_constants (B ctxt) in let contract = Stdlib.List.hd contracts in let expected_size = + (* TODO: create ZK constant *) + let origination_size = constants.parametric.tx_rollup.origination_size in let init_account = Zk_rollup.Account. { @@ -131,15 +135,19 @@ let test_origination_fees () = circuits_info = of_plonk_smap Operator.circuits; nb_ops = 1; }; - dynamic = {state = Operator.init_state}; + dynamic = + { + state = Operator.init_state; + paid_l2_operations_storage_space = Z.of_int origination_size; + used_l2_operations_storage_space = Z.zero; + }; } in let init_pl = Zk_rollup.(Empty {next_index = 0L}) in - Zk_rollup.Address.size + origination_size + 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 @@ -220,6 +228,517 @@ let test_originate_two_rollups () = assert (zk_rollup1 <> zk_rollup2) ; return_unit +(* Initializes the context and originates a ZKRU with [n_pending] + operations. *) +let init_with_pending ?(n_pending = 1) n = + let* ctxt, contracts, zk_rollup = init_and_originate n in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let* operation = + Op.zk_rollup_publish + (B ctxt) + contract + ~zk_rollup + ~ops: + (Stdlib.List.init n_pending (fun i -> + no_ticket + @@ + if i mod 2 = 0 then false_op pkh zk_rollup + else true_op pkh zk_rollup)) + in + let* b = Block.bake ~operation ctxt in + return (b, contracts, zk_rollup, pkh) + +(* Test for an invalid append: + The operation being appended has an invalid op code. +*) +let test_append_out_of_range_op_code () = + let* ctxt, contracts, zk_rollup = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let l2_op = false_op pkh zk_rollup in + let* i = Incremental.begin_construction ctxt in + let* operation = + Op.zk_rollup_publish + (I i) + contract + ~zk_rollup + ~ops:[no_ticket {l2_op with op_code = 1}] + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error (Zk_rollup_storage.Zk_rollup_invalid_op_code 1)) + i + operation + in + return_unit + +(* Test for an invalid append: + The operation being appended through an external op has positive price. +*) +let test_append_external_deposit () = + let* ctxt, contracts, zk_rollup = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let l2_op = false_op pkh zk_rollup in + let* i = Incremental.begin_construction ctxt in + let* operation = + Op.zk_rollup_publish + (I i) + contract + ~zk_rollup + ~ops: + [no_ticket {l2_op with price = {l2_op.price with amount = Z.of_int 10}}] + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Deposit_as_external) + i + operation + in + return_unit + +(* ------------------------- TESTS WITH TICKETS ------------------------- *) + +(** [make_ticket_key ty contents ticketer zk_rollup] computes the ticket hash + of the ticket containing [contents] of type [ty], crafted by [ticketer] and + owned by [zk_rollup]. *) +let make_ticket_key ctxt ~ty ~contents ~ticketer zk_rollup = + (match ctxt with + | Context.B block -> Incremental.begin_construction block + | Context.I incr -> return incr) + >>=? fun incr -> + let ctxt = Incremental.alpha_ctxt incr in + Script_ir_translator.parse_comparable_ty ctxt ty + >>??= fun (Ex_comparable_ty contents_type, ctxt) -> + Script_ir_translator.parse_comparable_data ctxt contents_type contents + >>=?? fun (contents, ctxt) -> + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Zk_rollup zk_rollup) + (Ticket_token.Ex_token {ticketer; contents_type; contents}) + >|=?? fst + +module Make_ticket (T : sig + val ty_str : string + + type contents + + type contents_type + + val contents_type : contents_type Script_typed_ir.comparable_ty + + val contents_to_micheline : contents -> contents_type + + val contents_to_string : contents -> string +end) (C : sig + val contents : T.contents +end) = +struct + include T + include C + + let ty = Expr.from_string ty_str + + let ex_token ~ticketer = + Ticket_token.Ex_token + {ticketer; contents_type; contents = contents_to_micheline contents} + + let contents_string = contents_to_string contents + + let contents_expr = Expr.from_string contents_string + + let ticket_hash ctxt ~ticketer ~zk_rollup = + make_ticket_key + ctxt + ~ty:(Tezos_micheline.Micheline.root ty) + ~contents:(Tezos_micheline.Micheline.root contents_expr) + ~ticketer + zk_rollup + + let zkru_ticket ~ticketer : Zk_rollup.Ticket.t = + Zk_rollup.Ticket.{contents = contents_expr; ty; ticketer} + + let init_deposit_contract amount block account = + let script = + Format.asprintf + {| parameter (pair address bytes); + storage unit; + code { + # cast the address to contract type + CAR; + UNPAIR; + CONTRACT %%deposit (pair (ticket %s) bytes); + ASSERT_SOME; + SWAP; + PUSH mutez 0; + SWAP; + # create a ticket + PUSH nat %a; + PUSH %s %s; + TICKET; + ASSERT_SOME; + PAIR ; + TRANSFER_TOKENS; + PUSH unit Unit; + NIL operation; + DIG 2 ; + CONS; + PAIR } |} + ty_str + Z.pp_print + amount + ty_str + contents_string + in + Contract_helpers.originate_contract_from_string + ~baker:(Context.Contract.pkh account) + ~source_contract:account + ~script + ~storage:"Unit" + block + + let deposit_op ~block ~zk_rollup ~(zk_op : Zk_rollup.Operation.t) ~account + ~deposit_contract = + let zk_op_literal = + let bytes = + Data_encoding.Binary.to_bytes_exn Zk_rollup.Operation.encoding zk_op + in + let (`Hex hex) = Hex.of_bytes bytes in + "0x" ^ String.uppercase_ascii hex + in + Op.transaction + (B block) + ~entrypoint:Entrypoint.default + ~parameters: + (Script.lazy_expr @@ Expr.from_string + @@ Printf.sprintf + {| Pair %S %s |} + (Zk_rollup.Address.to_b58check zk_rollup) + zk_op_literal) + ~fee:Tez.one + account + deposit_contract + (Tez.of_mutez_exn 0L) + + (** Return an operation to originate a contract that will deposit [amount] + tickets with l2 operation [op] on [zk_rollup] *) + let init_deposit ~block ~amount ~zk_op ~zk_rollup ~account = + init_deposit_contract amount block account + >>=? fun (deposit_contract, _script, block) -> + deposit_op ~block ~zk_rollup ~zk_op ~account ~deposit_contract + >|=? fun op -> (block, op, deposit_contract) +end + +module Nat_ticket = Make_ticket (struct + let ty_str = "nat" + + type contents = int + + type contents_type = Script_int.n Script_int.num + + let contents_type = Script_typed_ir.nat_t + + let contents_to_string = string_of_int + + let contents_to_micheline c = + WithExceptions.Option.get ~loc:__LOC__ @@ Script_int.(of_int c |> is_nat) +end) + +module String_ticket = Make_ticket (struct + let ty_str = "string" + + type contents = string + + type contents_type = Script_string.t + + let contents_type = Script_typed_ir.string_t + + let contents_to_string s = "\"" ^ s ^ "\"" + + let contents_to_micheline c = + WithExceptions.Result.get_ok ~loc:__LOC__ Script_string.(of_string c) +end) + +let test_append_errors () = + let open Zk_rollup.Operation in + (* Create two accounts and 1 zk rollup *) + let* block, contracts, zk_rollup = init_and_originate 2 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + (* Preparing operation and ticket for tests *) + let op = + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + false_op pkh zk_rollup + in + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let ticket = Nat_ticket.zkru_ticket ~ticketer:contract0 in + (* Start generating block *) + let* i = Incremental.begin_construction block in + (* Send ticket but price = 0 *) + let* operation = + let price = {id = ticket_hash; amount = Z.zero} in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[({op with price}, Some ticket)] + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + (* None ticket, price < 0 *) + let* operation = + let price = {id = ticket_hash; amount = Z.of_string "-10"} in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[no_ticket {op with price}] + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + (* Some ticket, price < 0, op.price ≠ hash(ticket, zkru) *) + let* operation = + let price = + { + id = Ticket_hash.of_bytes_exn (Bytes.create 32); + amount = Z.of_string "-10"; + } + in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[({op with price}, Some ticket)] + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_ticket) + i + operation + in + return_unit + +let assert_ticket_balance ~loc incr token owner expected = + let ctxt = Incremental.alpha_ctxt incr in + Ticket_balance_key.of_ex_token ctxt ~owner token >>=?? fun (key_hash, ctxt) -> + Ticket_balance.get_balance ctxt key_hash >>=?? fun (balance, _) -> + match (balance, expected) with + | Some b, Some e -> Assert.equal_int ~loc (Z.to_int b) e + | Some b, None -> + failwith "%s: Expected no balance but got some %d" loc (Z.to_int b) + | None, Some b -> failwith "%s: Expected balance %d but got none" loc b + | None, None -> return () + +let test_invalid_deposit () = + (* Create 2 accounts and one zk rollups *) + let* block, contracts, zk_rollup = init_and_originate 5 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + let contract2 = Stdlib.List.nth contracts 2 in + let contract3 = Stdlib.List.nth contracts 3 in + let contract4 = Stdlib.List.nth contracts 4 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let token = Nat_ticket.ex_token ~ticketer:deposit_contract in + (* Generate ticket created by deposit contract and owned by rollup *) + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + (* ----- Start generating block *) + let* i = Incremental.begin_construction block in + (* check rollup exists with none of these particular tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- op.price = 0 *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 0}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract0 + ~deposit_contract + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- hash(ticket, zkru) <> op.price *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = + {id = Ticket_hash.of_bytes_exn (Bytes.create 32); amount = Z.of_int 10}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract1 + ~deposit_contract + in + let* i = + Incremental.add_operation + i + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_ticket) + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- op.price <> ticket amount *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 12}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract2 + ~deposit_contract + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- ticket amount = 0 *) + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 0) block contract0 + in + (* Create append/deposit operation with ticket *) + let zk_op = + {(false_op pkh zk_rollup) with price = {id = ticket_hash; amount = Z.zero}} + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract3 + ~deposit_contract + in + let* i = Incremental.begin_construction block in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error_f (function + | Script_interpreter.Runtime_contract_error _ -> true + | _ -> false)) + i + operation + in + + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- ticket size > Constants.tx_rollup_max_ticket_payload_size *) + (* Contents size is such that, together with the ticketer address, + they exceed the maximum size of an operation *) + let contents_size = 15_000 in + let module String_ticket = String_ticket (struct + let contents = String.make contents_size 'a' + end) in + let* deposit_contract, _script, block = + String_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let* ticket_hash = + String_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let token = String_ticket.ex_token ~ticketer:deposit_contract in + (* Create append/deposit operation with ticket *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 10}; + } + in + let* operation = + String_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract4 + ~deposit_contract + in + let* i = Incremental.begin_construction block in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + let* limit = + let* constants = Context.get_constants (I i) in + constants.parametric.tx_rollup.max_ticket_payload_size |> return + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error + (Zk_rollup.Errors.Ticket_payload_size_limit_exceeded + {payload_size = contents_size + 216; limit})) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + return_unit + let tests = [ Tztest.tztest @@ -232,4 +751,11 @@ let tests = "origination negative nb_ops" `Quick test_origination_negative_nb_ops; + Tztest.tztest + "append with invalid op code" + `Quick + test_append_out_of_range_op_code; + Tztest.tztest "append external deposit" `Quick test_append_external_deposit; + Tztest.tztest "append check errors" `Quick test_append_errors; + Tztest.tztest "invalid deposit" `Quick test_invalid_deposit; ] 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 9915b8ec7120569749496e27ed70d818ab7623af..1a191fb004c23ce73727b38f4615fd095d9d9963 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 @@ -99,6 +99,7 @@ type manager_operation_kind = | K_Sc_rollup_recover_bond | K_Dal_publish_slot_header | K_Zk_rollup_origination + | K_Zk_rollup_publish (** The requirements for a tested manager operation. *) type operation_req = { @@ -201,6 +202,7 @@ let kind_to_string = function | 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" + | K_Zk_rollup_publish -> "Zk_rollup_publish" (** {2 Pretty-printers} *) let pp_opt pp v = @@ -1060,6 +1062,27 @@ let mk_zk_rollup_origination (oinfos : operation_req) (infos : infos) = in return op +let mk_zk_rollup_publish (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let open Zk_rollup.Operation in + let* zk_rollup = zk_rollup_of infos.ctxt.zk_rollup in + let l2_op = + {ZKOperator.Internal_for_tests.false_op with rollup_id = zk_rollup} + in + let* op = + Op.zk_rollup_publish + ?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) + ~zk_rollup + ~ops:[(l2_op, None)] + in + return op + (** {2 Helpers for generation of generic check tests by manager operation} *) (** Generic forge for any kind of manager operation according to @@ -1096,6 +1119,7 @@ let select_op (op_req : operation_req) (infos : infos) = | 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 + | K_Zk_rollup_publish -> mk_zk_rollup_publish in mk_op op_req infos @@ -1442,7 +1466,7 @@ let is_consumer = function | 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_Zk_rollup_origination -> + | K_Zk_rollup_origination | K_Zk_rollup_publish -> false | K_Transaction | K_Origination | K_Register_global_constant | K_Tx_rollup_dispatch_tickets | K_Transfer_ticket -> @@ -1469,4 +1493,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 + | K_Zk_rollup_origination | K_Zk_rollup_publish -> 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 26b86c64a4672aa78b5f7bc57df03151fde2f2b4..4ce862ab8a77f9b595e499ebfa69c65cbaeb2914 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 @@ -85,7 +85,8 @@ let ensure_kind infos kind = | 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 - | Zk_rollup_origination _, K_Zk_rollup_origination -> + | Zk_rollup_origination _, K_Zk_rollup_origination + | Zk_rollup_publish _, K_Zk_rollup_publish -> return_unit | ( ( Transaction _ | Origination _ | Register_global_constant _ | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ @@ -98,7 +99,7 @@ let ensure_kind infos kind = | Sc_rollup_refute _ | Sc_rollup_timeout _ | Sc_rollup_execute_outbox_message _ | Sc_rollup_recover_bond _ | Dal_publish_slot_header _ | Sc_rollup_dal_slot_subscribe _ - | Zk_rollup_origination _ ), + | Zk_rollup_origination _ | Zk_rollup_publish _ ), _ ) -> assert false) | Single _ -> assert false 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 index 95afbc9f3ef9f409f5f0de90c336763edbdb325c..042fe450eb133609823354c72933fcba5b43739b 100644 --- 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 @@ -69,7 +69,7 @@ let gen_zkr_account = let circuits_info = SMap.of_seq (Plonk.Main_protocol.SMap.to_seq Operator.circuits) in - let+ nb_ops = nat in + let* nb_ops = nat in let static = { public_parameters; @@ -78,7 +78,18 @@ let gen_zkr_account = nb_ops; } in - let dynamic = {state} in + let* paid_l2_operations_storage_space = nat in + let+ used_l2_operations_storage_space = + map Z.of_int @@ int_bound paid_l2_operations_storage_space + in + let dynamic = + { + state; + paid_l2_operations_storage_space = + Z.of_int paid_l2_operations_storage_space; + used_l2_operations_storage_space; + } + in {static; dynamic} let gen_ticket_hash = @@ -97,7 +108,12 @@ let gen_z = 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* price = + map2 + (fun id amount -> Zk_rollup_operation_repr.{id; amount}) + 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 diff --git a/src/proto_alpha/lib_protocol/test/unit/test_destination_repr.ml b/src/proto_alpha/lib_protocol/test/unit/test_destination_repr.ml index 6bb7638b99f2388a62d184df835bc627c4933ad4..830251241aecf68704369a74aecc79cfc2f7bac7 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_destination_repr.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_destination_repr.ml @@ -81,6 +81,10 @@ let tx_rollup_address = "txr1YNMEtkj5Vkqsbdmt7xaxBTMRZjzS96UAi" *) let sc_rollup_address = "scr1HLXM32GacPNDrhHDLAssZG88eWqCUbyLF" +(* TODO: https://gitlab.com/tezos/tezos/-/issues/3731 + Explain how this address was computed *) +let zk_rollup_address = "zkr1RePaz42fAmoGVGPhRvoVH5zwr3Sz6ZS93" + let assert_compat contract destination = match destination with | Destination_repr.Contract contract' @@ -180,11 +184,13 @@ let test_compare_destination () = let kt1 = !!(Destination_repr.of_b58check liquidity_baking_dex) in let txr1 = !!(Destination_repr.of_b58check tx_rollup_address) in let scr1 = !!(Destination_repr.of_b58check sc_rollup_address) in + let zkr1 = !!(Destination_repr.of_b58check zk_rollup_address) in assert (Destination_repr.(tz1 < kt1)) ; assert (Destination_repr.(kt1 < txr1)) ; assert (Destination_repr.(tz1 < txr1)) ; assert (Destination_repr.(txr1 < scr1)) ; + assert (Destination_repr.(scr1 < zkr1)) ; return_unit 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 index ffcf640b9aa27675c7f961ecc8a55ab115d972fa..f776e4c9cc6c6ce4d19b4179b4efda627923abe9 100644 --- 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 @@ -134,6 +134,83 @@ module Raw_context_tests = struct let** _ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in assert (Helpers.is_empty pending) ; return_unit + + (* Check that appending an L2 operation with the [add_to_pending] helper + correctly updates both the pending list descriptor and the actual + operations under the [pending_operations] directory. *) + let pending_list_append () = + let open Lwt_result_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _, _ = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + (* Append first operation *) + let** ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let** ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.pending_length pending = 1) ; + let* ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (List.length ops = 1) ; + (* Append second operation *) + let** ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let** ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + let* _ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (Helpers.pending_length pending = 2) ; + assert (List.length ops = 2) ; + return_unit + + let pending_list_append_errors () = + let open Lwt_result_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _, _ = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + (* Append first operation *) + let** ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let** ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.pending_length pending = 1) ; + let* ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (List.length ops = 1) ; + (* Invalid op code *) + let wrong_op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 1; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + let*! e = Zk_rollup_storage.add_to_pending ctx rollup [wrong_op] >>= wrap in + let* () = + Assert.proto_error_with_info ~loc:__LOC__ e "Invalid op code in append" + in + (* Invalid rollup address *) + let* _ctx, nonce = Raw_context.increment_origination_nonce ctx |> wrap in + let* address = + Zk_rollup_repr.Address.from_nonce (Origination_nonce.incr nonce) |> wrap + in + let*! _e = Zk_rollup_storage.add_to_pending ctx address [op] >>= wrap in + return_unit end let tests = @@ -142,4 +219,12 @@ let tests = "origination_pending_is_empty" `Quick Raw_context_tests.pending_list_origination_is_empty; + Tztest.tztest + "pending_list_append" + `Quick + Raw_context_tests.pending_list_append; + Tztest.tztest + "pending_list_append errors" + `Quick + Raw_context_tests.pending_list_append_errors; ] diff --git a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml index 6ecac3020a56d6872f770b9737d2b2714787c54e..01f67f8fea7b5b16748ad7a9defdf7d4b260d83e 100644 --- a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml +++ b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml @@ -207,6 +207,21 @@ let tickets_of_operation ctxt ~destination:(Destination.Sc_rollup destination) ~parameters_ty ~parameters + | Transaction_to_zk_rollup + { + destination; + unparsed_parameters = _; + parameters_ty = Pair_t (Ticket_t (ty, _), Bytes_t, _, _); + parameters = ticket, _op; + } -> + let ex_ticket = Ticket_scanner.Ex_ticket (ty, ticket) in + return + ( Some + { + destination = Destination.Zk_rollup destination; + tickets = [ex_ticket]; + }, + ctxt ) | Origination { delegate = _; diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.ml b/src/proto_alpha/lib_protocol/ticket_scanner.ml index 4993572e9fa717453a641bd7a7bd827c15b07977..83a9b8f90c8d216d298b304942182dac0bef29ee 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.ml +++ b/src/proto_alpha/lib_protocol/ticket_scanner.ml @@ -543,3 +543,20 @@ let tickets_of_node ctxt ~include_lazy has_tickets expr = expr >>=? fun (value, ctxt) -> tickets_of_value ctxt ~include_lazy has_tickets value + +let ex_ticket_size ctxt (Ex_ticket (ty, ticket)) = + (* type *) + Script_typed_ir.ticket_t Micheline.dummy_location ty >>?= fun ty -> + Script_ir_unparser.unparse_ty ~loc:Micheline.dummy_location ctxt ty + >>?= fun (ty', ctxt) -> + let ty_nodes, ty_size = Script_typed_ir_size.node_size ty' in + let ty_size = Saturation_repr.to_int ty_size in + let ty_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:ty_nodes in + Gas.consume ctxt ty_size_cost >>?= fun ctxt -> + (* contents *) + let val_nodes, val_size = Script_typed_ir_size.value_size ty ticket in + let val_size = Saturation_repr.to_int val_size in + let val_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:val_nodes in + Gas.consume ctxt val_size_cost >>?= fun ctxt -> + (* gas *) + return (ty_size + val_size, ctxt) diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.mli b/src/proto_alpha/lib_protocol/ticket_scanner.mli index 209c633ab74abb5a5dd1cd91cd5b3e93c6f01e3d..1b40bed183e8e0920ed778288dcfa709ca211dd5 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.mli +++ b/src/proto_alpha/lib_protocol/ticket_scanner.mli @@ -90,3 +90,10 @@ val tickets_of_node : (** [has_tickets ht] returns whether or not the type of the given [has_tickets] witness [ht] has tickets. *) val has_tickets : 'a has_tickets -> bool + +(** [ex_ticket_size ctxt ex_ticket] returns the size of the in-memory representation of + [ex_ticket] in bytes. *) +val ex_ticket_size : + Alpha_context.context -> + ex_ticket -> + (int * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/tx_rollup_repr.ml b/src/proto_alpha/lib_protocol/tx_rollup_repr.ml index 5fcfc6be3b6338fea2de7d86c6089c86f42ea669..5e4416e66982553edab038304e7329b813c0394b 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_repr.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_repr.ml @@ -152,8 +152,6 @@ module Index = struct let compare = compare end -let deposit_entrypoint = Entrypoint_repr.of_string_strict_exn "deposit" - module Cmp = struct type nonrec t = t diff --git a/src/proto_alpha/lib_protocol/tx_rollup_repr.mli b/src/proto_alpha/lib_protocol/tx_rollup_repr.mli index 301d8a8009de925f6375658bd5cc9e579f1e1481..18f15b2b7c11520919a8b849809ebb5125fc2672 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_repr.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_repr.mli @@ -64,10 +64,6 @@ val rpc_arg : t RPC_arg.arg module Index : Storage_description.INDEX with type t = t -(** The entrypoint a layer-1 contract can use to deposit Michelson tickets - into a transaction rollup. *) -val deposit_entrypoint : Entrypoint_repr.t - module Set : Set.S with type elt = t module Map : Map.S with type key = t diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 49ac6f8a5264bef134fdd31fd4abb38f8a854b41..5cb0651960337bbd6c45c42eefdf271de971e304 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1952,7 +1952,7 @@ 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 _ -> + | Zk_rollup_origination _ | Zk_rollup_publish _ -> let* () = assert_zk_rollup_feature_enabled vi in return remaining_gas in diff --git a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml index d9a6b421bb5ee30c957dc3901a64f3e6fdda5b57..7e04917bdb1e3ad8d6a3b9416ffd29ce9514dcdb 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.ml @@ -32,7 +32,11 @@ type static = { nb_ops : int; } -type dynamic = {state : Zk_rollup_state_repr.t} +type dynamic = { + state : Zk_rollup_state_repr.t; + paid_l2_operations_storage_space : Z.t; + used_l2_operations_storage_space : Z.t; +} type t = {static : static; dynamic : dynamic} @@ -71,9 +75,26 @@ let encoding = in let dynamic_encoding = conv - (fun {state} -> state) - (fun state -> {state}) - (obj1 (req "state" Zk_rollup_state_repr.encoding)) + (fun { + state; + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + } -> + ( state, + paid_l2_operations_storage_space, + used_l2_operations_storage_space )) + (fun ( state, + paid_l2_operations_storage_space, + used_l2_operations_storage_space ) -> + { + state; + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + }) + (obj3 + (req "state" Zk_rollup_state_repr.encoding) + (req "paid_l2_operations_storage_space" n) + (req "used_l2_operations_storage_space" n)) in conv (fun {static; dynamic} -> (static, dynamic)) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli index c84c94746dd2ceeafbd23d646e7d20d92dbfc080..7a87437c22d456ee3fccf23744d891714c277d9b 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli +++ b/src/proto_alpha/lib_protocol/zk_rollup_account_repr.mli @@ -45,6 +45,12 @@ type dynamic = { state : Zk_rollup_state_repr.t; (** Array of scalars representing the state of the rollup at a given level. *) + paid_l2_operations_storage_space : Z.t; + (** Number of bytes for storage of L2 operations that have + been already paid for. *) + used_l2_operations_storage_space : Z.t; + (** Number of bytes for storage of L2 operations that are + being used. *) } type t = {static : static; dynamic : dynamic} diff --git a/src/proto_alpha/lib_protocol/zk_rollup_apply.ml b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml index 2d6704f98221a94229130774d14fb3142bb34c28..200bcc420d83c62b2c4e3f4ca9d45d521211e1cf 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_apply.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml @@ -81,3 +81,158 @@ let originate ~ctxt_before_op ~ctxt ~public_parameters ~circuits_info } in (ctxt, result, []) + +(** [parse_ticket ~ticketer ~contents ~ty ctxt] reconstructs a ticket from + individual parts submitted as part of a Zk_rollup_publish operation. *) +let parse_ticket ~ticketer ~contents ~ty ctxt = + Script_ir_translator.parse_comparable_ty ctxt (Micheline.root ty) + >>?= fun (Ex_comparable_ty contents_type, ctxt) -> + Script_ir_translator.parse_comparable_data + ctxt + contents_type + (Micheline.root contents) + >>=? fun (contents, ctxt) -> + return @@ (ctxt, Ticket_token.Ex_token {ticketer; contents_type; contents}) + +let publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops = + let open Lwt_result_syntax in + let*? () = assert_feature_enabled ctxt in + + let open Zk_rollup.Operation in + (* Deposits (i.e. L2 operations with a positive price) cannot be published + through an external operation *) + let*? () = + error_unless + (List.for_all + (fun (l2_op, _ticket_opt) -> Compare.Z.(l2_op.price.amount <= Z.zero)) + l2_ops) + Zk_rollup.Errors.Deposit_as_external + in + (* Check that for every operation to publish: + 1. Their price is zero iff they have no ticket representation + 2. The "token id" of its price is the correct ticket hash + Additionally, for operations with tickets, the hash of the ticket + with the l1 destination from the operation's header is computed. + *) + let* ctxt, l2_ops_with_ticket_hashes = + List.fold_left_map_es + (fun ctxt (l2_op, ticket_opt) -> + match ticket_opt with + | None -> + let*? () = + error_unless + Compare.Z.(l2_op.price.amount = Z.zero) + Zk_rollup.Errors.Invalid_deposit_amount + in + return (ctxt, (l2_op, None)) + | Some Zk_rollup.Ticket.{ticketer; ty; contents} -> + let*? () = + error_when + Compare.Z.(l2_op.price.amount = Z.zero) + Zk_rollup.Errors.Invalid_deposit_amount + in + let* ctxt, ticket_token = + parse_ticket ~ticketer ~contents ~ty ctxt + in + (* Compute the ticket hash with L1 address to be able + to perform an exit / return token *) + let* receiver_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Contract (Implicit l2_op.l1_dst)) + ticket_token + in + (* Compute the ticket with zk rollup as owner, this is the hash + that is used as token identifier inside the ZKRU (and this + should be price's identifier in this L2 op) *) + let* source_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Zk_rollup zk_rollup) + ticket_token + in + let*? () = + error_unless + Ticket_hash.(equal l2_op.price.id source_ticket_hash) + Zk_rollup.Errors.Invalid_deposit_ticket + in + return (ctxt, (l2_op, Some receiver_ticket_hash))) + ctxt + l2_ops + in + let+ ctxt, paid_storage_size_diff = + Zk_rollup.add_to_pending ctxt zk_rollup l2_ops_with_ticket_hashes + in + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Apply_results.Zk_rollup_publish_result + {balance_updates = []; consumed_gas; paid_storage_size_diff} + in + (ctxt, result, []) + +let transaction_to_zk_rollup ~ctxt ~parameters_ty ~parameters ~dst_rollup ~since + = + let open Lwt_result_syntax in + let*? () = assert_feature_enabled ctxt in + let*? {ex_ticket; zkru_operation} = + Zk_rollup_parameters.get_deposit_parameters parameters_ty parameters + in + let* ticket_size, ctxt = Ticket_scanner.ex_ticket_size ctxt ex_ticket in + let limit = Constants.tx_rollup_max_ticket_payload_size ctxt in + let*? () = + error_when + Compare.Int.(ticket_size > limit) + (Zk_rollup.Errors.Ticket_payload_size_limit_exceeded + {payload_size = ticket_size; limit}) + in + let ex_token, ticket_amount = + Ticket_token.token_and_amount_of_ex_ticket ex_ticket + in + (* Compute the ticket hash with zk rollup as owner *) + let* ticket_hash, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Zk_rollup dst_rollup) ex_token + in + let ticket_amount = Script_int.(to_zint (ticket_amount :> n num)) in + (* Check that the amount and id of the transferred ticket are what + the operation's price claims. *) + let*? () = + error_unless + Compare.Z.(ticket_amount = zkru_operation.price.amount) + Zk_rollup.Errors.Invalid_deposit_amount + in + let*? () = + error_unless + Ticket_hash.(equal ticket_hash zkru_operation.price.id) + Zk_rollup.Errors.Invalid_deposit_ticket + in + (* Compute the ticket hash with L1 address to be able + to perform an exit / return token *) + let* receiver_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Contract (Implicit zkru_operation.l1_dst)) + ex_token + in + (* Add it to the rollup pending list *) + let+ ctxt, paid_storage_size_diff = + Zk_rollup.add_to_pending + ctxt + Zk_rollup.Operation.(zkru_operation.rollup_id) + [(zkru_operation, Some receiver_ticket_hash)] + in + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + let result = + Apply_internal_results.( + ITransaction_result + (Transaction_to_zk_rollup_result + { + balance_updates = []; + consumed_gas = Gas.consumed ~since ~until:ctxt; + ticket_hash; + paid_storage_size_diff; + })) + in + (ctxt, result, []) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_apply.mli b/src/proto_alpha/lib_protocol/zk_rollup_apply.mli index 0fd88b7de2b8a6720718730ccea15dc1c6d050df..81b27dffd0efb7b646edba0bb1d18656c3ceaadd 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_apply.mli +++ b/src/proto_alpha/lib_protocol/zk_rollup_apply.mli @@ -29,6 +29,62 @@ feature flag is enabled. *) +(** In the ZK Rollup, L2 operations are validated in two steps: + {ol + {li The Protocol does the first pass of (light) validation and + appends the L2 operation to a pending list.} + {li The ZKRU Operator does the second pass of validation for a prefix + of the pending list and posts a proof on chain of the validity of + each of them. + Based on this proof, the Protocol is going to remove the prefix + from the pending list, and apply their effect on the ZKRU L2 state + and on the L1 balances.} + } + + The first step of validation is split into two cases, depending on + the type of L2 operation that is being submitted: + {ul + {li If the application of said L2 operation results in a transfer + of a ticket from L1 to L2 (i.e. it is a ZKRU {i deposit}), the + L2 operation has to be submitted through a call to the ZKRU + [%deposit] entrypoint from a smart contract. + This constraint is imposed by the fact that implicit accounts + cannot transfer tickets. + Then, the validation of these L2 operations will be performed + when applying the internal Tezos operation emitted by the call + to the ZKRU's deposit entrypoint. This is implemented by the + [transaction_to_zk_rollup] function in this module. + } + {li If its application results in a ticket transfer from L2 to L1 + (i.e. it is a ZKRU {i withdrawal}) or it has no transfer between + layers, the L2 operation has to be submitted through a + [Zk_rollup_publish] external Tezos operation. + The checks for these L2 operations will be perform upon application + of said external Tezos operation, whose logic is implemented by the + [publish] function in this module. + } + } + + Although L2 operations are mostly opaque, they expose a header that is + transparent to the Protocol (see {!Zk_rollup_operation_repr.t}). + In this header there's a field for the [price] of an L2 operation, which + will expose its kind. Concretely, the [price] encodes the net ticket + transfer from L1 to L2 caused by an L2 operation. Then, deposits have + a positive price, withdrawals a negative one, and pure L2 operations + must have a price of zero. + + An L2 operation's price also encodes which ticket is being transferred, + by storing the ticket's hash (see {!Ticket_hash_repr}). These hashes are + used as token identifiers inside the ZKRU. In both cases, the L2 operations + with a non-zero price (i.e. deposits and withdrawals) will be submitted + alongside the values describing the ticket being transferred + (see {!Zk_rollup_ticket_repr}). These values have to be consistent with + the token identifier used in the L2 operation's price. + + NB: if ticket transfers by implicit accounts was supported, these two cases + could be unified into the application of the [Zk_rollup_publish] operation. +*) + open Alpha_context (** These errors are only to be matched in tests. *) @@ -74,3 +130,106 @@ val originate : * Script_typed_ir.packed_internal_operation list) tzresult Lwt.t + +(** [publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops] + applies a publish operation to [zk_rollup] by adding [l2_ops] to its + pending list. + + All L2 operations in [l2_ops] must claim a non-positive [price] + (see {!Zk_rollup_operation_repr}). In other words, no deposit is + allowed in this operation, as those must go through an internal + transaction. + + This function will first perform a series of validation checks over + the L2 operations in [l2_ops]. If all of them are successful, these L2 + operations will be added to [dst_rollup]'s pending list. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated. + } + {li [Zk_rollup.Errors.Deposit_as_external] if the price of an L2 + operation from [ops] is positive. + } + {li [Zk_rollup.Errors.Invalid_deposit_amount] if an L2 operation + declares no ticket but has a non-zero price or if it declares + a ticket with a price of zero. + } + {li [Zk_rollup.Errors.Invalid_deposit_ticket] if an L2 operation's + ticket identifier (see [Zk_rollup_operation_repr]) is different from + the hash of its corresponding ticket and [l1_dst]. + } + {li [Zk_rollup_storage.Zk_rollup_invalid_op_code op_code] if the + [op_code] of one of the [operations] is greater or equal + to the number of declared operations for this [zk_rollup]. + } + } +*) +val publish : + ctxt_before_op:t -> + ctxt:t -> + zk_rollup:Zk_rollup.t -> + l2_ops:(Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list -> + (t + * Kind.zk_rollup_publish Apply_results.successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t + +(** [transaction_to_zk_rollup + ~ctxt ~parameters_ty ~parameters ~payer ~dst_rollup ~since] applies an + internal transaction to a ZK [dst_rollup]. + + Internal transactions are used for deposits into ZK rollups, which can + be seen as a special case of the publish ZK rollup operation. + The [parameters] should include a ticket and a ZKRU L2 operation, as + explained in the {!Zk_rollup_parameters} module's documentation. + + This function will first perform a series of validation checks. + If successful, the L2 operation from the [parameters] will be added + to [dst_rollup]'s pending list, and [payer] will pay for the + added storage. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated. + } + {li [Zk_rollup.Errors.Ticket_payload_size_limit_exceeded] if the ticket + found in the [parameters] exceeds the maximum ticket size. + } +u {li [Script_tc_errors.Forbidden_zero_ticket_quantity] if the ticket + amount is zero. + } + {li [Zk_rollup.Errors.Invalid_deposit_amount] if the amount of the ticket + transferred to the [dst_rollup] is different from the [price] + (see {!Zk_rollup_operation_repr}) claimed by the L2 operation. + } + {li [Zk_rollup.Errors.Invalid_deposit_ticket] if the L2 operation's + ticket identifier (see {!Zk_rollup_operation_repr}) is different to + the hash of the transferred ticket and [dst_rollup]. + } + {li [Zk_rollup_storage.Zk_rollup_invalid_op_code op_code] if the + [op_code] of the operation from the [parameters] is greater or equal + to the number of declared operations for this rollup. + } + {li [Zk_rollup.Errors.Wrong_deposit_parameters] if the [parameters] + are not of the expected type. See {!Zk_rollup_parameters}. + } + } +*) +val transaction_to_zk_rollup : + ctxt:t -> + parameters_ty: + ( ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + 'b ) + Script_typed_ir.ty -> + parameters:('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + dst_rollup:Zk_rollup.t -> + since:t -> + (t + * Kind.transaction Apply_internal_results.successful_internal_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t diff --git a/src/proto_alpha/lib_protocol/zk_rollup_errors.ml b/src/proto_alpha/lib_protocol/zk_rollup_errors.ml new file mode 100644 index 0000000000000000000000000000000000000000..9e8b81c741eaa4160c986134d39bf930601d3006 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_errors.ml @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* 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 += + | Deposit_as_external + | Invalid_deposit_amount + | Invalid_deposit_ticket + | Wrong_deposit_parameters + | Ticket_payload_size_limit_exceeded of {payload_size : int; limit : int} + +let () = + register_error_kind + `Temporary + ~id:"operation.zk_rollup_deposit_as_external" + ~title:"Zk_rollup: attempted a deposit through an external op" + ~description:"Zk_rollup: attempted a deposit through an external op" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit through an external op") + Data_encoding.empty + (function Deposit_as_external -> Some () | _ -> None) + (fun () -> Deposit_as_external) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_invalid_deposit_amount" + ~title:"Zk_rollup: attempted a deposit with an invalid amount" + ~description:"Zk_rollup: attempted a deposit with an invalid amount" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit with an invalid amount") + Data_encoding.empty + (function Invalid_deposit_amount -> Some () | _ -> None) + (fun () -> Invalid_deposit_amount) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_invalid_deposit_ticket" + ~title:"Zk_rollup: attempted a deposit with an invalid ticket" + ~description:"Zk_rollup: attempted a deposit with an invalid ticket" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit with an invalid ticket") + Data_encoding.empty + (function Invalid_deposit_ticket -> Some () | _ -> None) + (fun () -> Invalid_deposit_ticket) ; + register_error_kind + `Permanent + ~id:"operation.zk_rollup_wrong_deposit_parameters" + ~title:"Zk_rollup: attempted a deposit with invalid parameters" + ~description:"Zk_rollup: attempted a deposit with invalid parameters" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Zk_rollup: attempted a deposit with an invalid parameters") + Data_encoding.empty + (function Wrong_deposit_parameters -> Some () | _ -> None) + (fun () -> Wrong_deposit_parameters) ; + register_error_kind + `Permanent + ~id:"zk_rollup_ticket_payload_size_limit_exceeded" + ~title:"The payload of the deposited ticket exceeded the size limit" + ~description:"The payload of the deposited ticket exceeded the size limit" + Data_encoding.(obj2 (req "payload_size" int31) (req "limit" int31)) + (function + | Ticket_payload_size_limit_exceeded {payload_size; limit} -> + Some (payload_size, limit) + | _ -> None) + (fun (payload_size, limit) -> + Ticket_payload_size_limit_exceeded {payload_size; limit}) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml index 66f4c227c4c9367c1a094398a242e00a94e21b20..bed1b50e6c63a926d1c91c69cb3e51105dcf0f38 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.ml @@ -23,9 +23,11 @@ (* *) (*****************************************************************************) +type price = {id : Ticket_hash_repr.t; amount : Z.t} + type t = { op_code : int; - price : Ticket_hash_repr.t * Z.t; + price : price; l1_dst : Signature.Public_key_hash.t; rollup_id : Zk_rollup_repr.t; payload : Zk_rollup_scalar.t array; @@ -46,14 +48,21 @@ let to_scalar_array {op_code; price; l1_dst; rollup_id; payload} = [ [| int_to_scalar op_code; - ticket_hash_to_scalar (fst price); - Zk_rollup_scalar.of_z (snd price); + ticket_hash_to_scalar price.id; + Zk_rollup_scalar.of_z price.amount; pkh_to_scalar l1_dst; Zk_rollup_repr.to_scalar rollup_id; |]; payload; ] +let price_encoding = + Data_encoding.( + conv + (fun {id; amount} -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (obj2 (req "id" Ticket_hash_repr.encoding) (req "amount" z))) + let encoding = Data_encoding.( conv @@ -63,7 +72,7 @@ let encoding = {op_code; price; l1_dst; rollup_id; payload}) (obj5 (req "op_code" int31) - (req "price" (tup2 Ticket_hash_repr.encoding z)) + (req "price" price_encoding) (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 index 1e3542ea7c4bc66bccf3c3e68a35022625b304d6..85ce349461bb9f87e5d70080f11941d98589de6a 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.mli +++ b/src/proto_alpha/lib_protocol/zk_rollup_operation_repr.mli @@ -23,15 +23,21 @@ (* *) (*****************************************************************************) +(** The [price] of an L2 operation represents the net ticket + transfer from L1 to L2 that it will produce. + [id] is a ticket hash used as a ticket identifier and [amount] + is 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. +*) +type price = {id : Ticket_hash_repr.t; amount : Z.t} + (** 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 The [price] of this L2 operation} {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} @@ -43,7 +49,7 @@ *) type t = { op_code : int; - price : Ticket_hash_repr.t * Z.t; + price : price; l1_dst : Signature.Public_key_hash.t; rollup_id : Zk_rollup_repr.t; payload : Zk_rollup_scalar.t array; diff --git a/src/proto_alpha/lib_protocol/zk_rollup_parameters.ml b/src/proto_alpha/lib_protocol/zk_rollup_parameters.ml new file mode 100644 index 0000000000000000000000000000000000000000..d41389d53e41f42d0f970a4ddebf7a2f7a3d10db --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_parameters.ml @@ -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. *) +(* *) +(*****************************************************************************) + +type deposit_parameters = { + ex_ticket : Ticket_scanner.ex_ticket; + zkru_operation : Alpha_context.Zk_rollup.Operation.t; +} + +let get_deposit_parameters : + type a comparable. + ( (a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + comparable ) + Script_typed_ir.ty -> + (a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + deposit_parameters tzresult = + fun ty contents -> + let open Script_typed_ir in + match (ty, contents) with + | Pair_t (Ticket_t (ty, _), Bytes_t, _, _), (ticket, op_bytes) -> ( + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Zk_rollup.Operation.encoding + op_bytes + with + | None -> error Alpha_context.Zk_rollup.Errors.Wrong_deposit_parameters + | Some zkru_operation -> + ok {ex_ticket = Ticket_scanner.Ex_ticket (ty, ticket); zkru_operation} + ) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_parameters.mli b/src/proto_alpha/lib_protocol/zk_rollup_parameters.mli new file mode 100644 index 0000000000000000000000000000000000000000..386d036b13bede8a7fe39e71a3bde93527734e3b --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_parameters.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* 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 module for representing and extracting typed ZK rollup + parameters. *) + +(** A type representing deposit parameters for ZK rollups. Deposit + parameters consist of a ticket of arbitrary content along with a + layer-2 ZKRU operation byte representation. *) +type deposit_parameters = { + ex_ticket : Ticket_scanner.ex_ticket; + zkru_operation : Alpha_context.Zk_rollup.Operation.t; +} + +(** [get_deposit_parameters ty value] returns [ex_ticket] and a + [zkru_operation] from a michelson typed value. if [ty] is not of a + pair of ticket and [bytes] then it fails with + [Zk_rollup_errors.Wrong_deposit_parameters]. + + This function is intended to be used to enforce the type of the transaction + to a [zk_rollup%deposit]. It must be used both in [ticket_diffs_of_operations] + to account for the ticket deposited and in [apply] to retrieve the ticket + when applying the transaction to a zk_rollup. *) +val get_deposit_parameters : + ( ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + 'comparable ) + Script_typed_ir.ty -> + ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + deposit_parameters tzresult diff --git a/src/proto_alpha/lib_protocol/zk_rollup_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_repr.ml index f52bda0a2718f01152c25acc443fced9e75b6db4..2bcb5a871118399c9b587fe76d56ef6dc4ec16c8 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_repr.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_repr.ml @@ -140,6 +140,10 @@ module Index = struct let compare = Address.compare end +let in_memory_size (_ : t) = + let open Cache_memory_helpers in + h1w +! string_size_gen Address.size + module Internal_for_tests = struct let originated_zk_rollup nonce = let data = diff --git a/src/proto_alpha/lib_protocol/zk_rollup_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_repr.mli index c8c940840fd5b8f0895b8a42c7f97d32a08204d4..52c028b4af226dfc7badf606279fc9565c546b2f 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_repr.mli +++ b/src/proto_alpha/lib_protocol/zk_rollup_repr.mli @@ -61,6 +61,10 @@ val pending_list_encoding : pending_list Data_encoding.t module Index : Storage_description.INDEX with type t = t +(** [in_memory_size zk_rollup] returns the number of bytes a [zk_rollup] + address uses in RAM. *) +val in_memory_size : t -> Cache_memory_helpers.sint + 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_storage.ml b/src/proto_alpha/lib_protocol/zk_rollup_storage.ml index db68462ca975e9bb6e7110a600c1f8812585e3b8..a6ffc7d7c66fac4c276dbcca61ba2e7ed401c367 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_storage.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_storage.ml @@ -23,7 +23,9 @@ (* *) (*****************************************************************************) -type error += Zk_rollup_does_not_exist of Zk_rollup_repr.t +type error += + | Zk_rollup_does_not_exist of Zk_rollup_repr.t + | Zk_rollup_invalid_op_code of int let () = register_error_kind @@ -35,14 +37,34 @@ let () = 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) + (fun x -> Zk_rollup_does_not_exist x) ; + register_error_kind + `Permanent + ~id:"Zk_rollup_invalid_op code" + ~title:"Invalid op code in append" + ~description:"Invalid op code in append" + ~pp:(fun ppf oc -> + Format.fprintf ppf "Op code %d is not valid for this ZK Rollup" oc) + Data_encoding.(obj1 (req "op_code" int31)) + (function Zk_rollup_invalid_op_code oc -> Some oc | _ -> None) + (fun oc -> Zk_rollup_invalid_op_code oc) 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 origination_size = Constants_storage.zk_rollup_origination_size ctxt in let initial_account = - Zk_rollup_account_repr.{static; dynamic = {state = init_state}} + Zk_rollup_account_repr. + { + static; + dynamic = + { + state = init_state; + paid_l2_operations_storage_space = Z.of_int origination_size; + used_l2_operations_storage_space = Z.zero; + }; + } in let* ctxt, account_size = Storage.Zk_rollup.Account.init ctxt address initial_account @@ -52,7 +74,95 @@ let originate ctxt static ~init_state = 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 + let size = + Z.of_int (origination_size + address_size + account_size + pl_size) + in return (ctxt, address, size) +let add_to_pending ctxt rollup ops = + let open Lwt_result_syntax in + let open Zk_rollup_repr in + let open Zk_rollup_operation_repr in + let* ctxt, acc = Storage.Zk_rollup.Account.get ctxt rollup in + let*? () = + List.iter_e + (fun (op, _ticket_hash_opt) -> + if Compare.Int.(op.op_code >= acc.static.nb_ops || op.op_code < 0) then + error @@ Zk_rollup_invalid_op_code op.op_code + else ok ()) + ops + in + let* ctxt, pl = Storage.Zk_rollup.Pending_list.get ctxt rollup in + let next_index, length = + match pl with + | Empty {next_index} -> (next_index, 0) + | Pending {next_index; length} -> (next_index, length) + in + let* ctxt, next_index, length, storage_diff = + List.fold_left_es + (fun (ctxt, next_index, length, storage_diff) op -> + let* ctxt, new_storage_diff, _was_bound = + Storage.Zk_rollup.Pending_operation.add (ctxt, rollup) next_index op + in + return + ( ctxt, + Int64.succ next_index, + length + 1, + new_storage_diff + storage_diff )) + (ctxt, next_index, length, 0) + ops + in + let used_l2_operations_storage_space = + Z.(add acc.dynamic.used_l2_operations_storage_space (Z.of_int storage_diff)) + in + let l2_operations_storage_space_to_pay = + Z.( + max + zero + (sub + used_l2_operations_storage_space + acc.dynamic.paid_l2_operations_storage_space)) + in + let paid_l2_operations_storage_space = + Z.( + add + acc.dynamic.paid_l2_operations_storage_space + l2_operations_storage_space_to_pay) + in + let acc = + { + acc with + dynamic = + { + acc.dynamic with + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + }; + } + in + + let pl = + if Compare.Int.(length = 0) then Empty {next_index} + else Pending {next_index; length} + in + (* Users aren't charged for storage diff in the account or pending list + description of a ZKRU. + When updating a ZKRU account, the storage diff can only come from the + dynamically sized [Z.t] used for the watermark. These changes + in storage size will not be accounted for. + As for the pending list description, the storage size is fixed for + each of the two cases (empty / non-empty). Then, there will be a storage + diff when switching between these two, which won't be accounted for + either. + *) + let* ctxt, _diff_acc = Storage.Zk_rollup.Account.update ctxt rollup acc in + let* ctxt, _diff_pl = Storage.Zk_rollup.Pending_list.update ctxt rollup pl in + return (ctxt, l2_operations_storage_space_to_pay) + +let assert_exist ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, exists = Storage.Zk_rollup.Account.mem ctxt rollup in + let*? () = error_unless exists (Zk_rollup_does_not_exist rollup) in + return ctxt + 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 index 35ae4b42b6dcf6de83a5bfd7ff4c49e5544f241a..74e18a914a74e66130376e3ada4e2fa058537246 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_storage.mli +++ b/src/proto_alpha/lib_protocol/zk_rollup_storage.mli @@ -28,6 +28,9 @@ 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. *) + | Zk_rollup_invalid_op_code of int + (** Emitted when trying to add to the pending list and operation + with an invalid op code. *) (** [originate context static ~init_state] produces an address [a] for a ZK rollup storage using the [origination_nonce] from @@ -43,6 +46,35 @@ val originate : init_state:Zk_rollup_state_repr.t -> (Raw_context.t * Zk_rollup_repr.t * Z.t) tzresult Lwt.t +(** [add_to_pending context rollup operations] appends to the + ZK [rollup]'s pending list a list of L2 [operations]. + Returns the new context alongside the size of the new operations. + + May fail with: + {ul + {li [Zk_rollup_invalid_op_code op_code] if the [op_code] + of one of the [operations] is greater or equal to the + number of declared operations for this [rollup]. + } + } +*) +val add_to_pending : + Raw_context.t -> + Zk_rollup_repr.t -> + (Zk_rollup_operation_repr.t * Ticket_hash_repr.t option) list -> + (Raw_context.t * Z.t) tzresult Lwt.t + +(** [assert_exist context rollup] asserts that [rollup] has been initialized. + Returns the new context. + + May fail with: + {ul + {li [Zk_rollup_does_not_exist] if [rollup] is not found.} + } +*) +val assert_exist : + Raw_context.t -> Zk_rollup_repr.t -> Raw_context.t tzresult Lwt.t + (** [exists context rollup] returns a boolean representing whether [rollup] has been initialized. *) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.ml b/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.ml new file mode 100644 index 0000000000000000000000000000000000000000..a8dfc557c5ac178759432506b0eb457501af0f9b --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.ml @@ -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. *) +(* *) +(*****************************************************************************) + +type t = { + contents : Script_repr.expr; + ty : Script_repr.expr; + ticketer : Contract_repr.t; +} + +let encoding : t Data_encoding.t = + let open Data_encoding in + conv + (fun {contents; ty; ticketer} -> (contents, ty, ticketer)) + (fun (contents, ty, ticketer) -> {contents; ty; ticketer}) + (obj3 + (req "contents" Script_repr.expr_encoding) + (req "ty" Script_repr.expr_encoding) + (req "ticketer" Contract_repr.encoding)) diff --git a/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.mli b/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.mli new file mode 100644 index 0000000000000000000000000000000000000000..34574e7c4f025f64a87d315b7bc519a2a8309999 --- /dev/null +++ b/src/proto_alpha/lib_protocol/zk_rollup_ticket_repr.mli @@ -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. *) +(* *) +(*****************************************************************************) + +(** Representation of tickets for the ZKRU. + This data is used by the [Zk_rollup_publish] operation to compute the + ticket hashes needed to transfer tickets from the ZK Rollup to an + implicit account. +*) +type t = { + contents : Script_repr.expr; + ty : Script_repr.expr; + ticketer : Contract_repr.t; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_tx_rollup/daemon.ml b/src/proto_alpha/lib_tx_rollup/daemon.ml index 257896966cb6808a9a98fd4c066daba62c347456..af4b1ccb7a5a8de7b9bd582e0663a5b2eb5cdd0a 100644 --- a/src/proto_alpha/lib_tx_rollup/daemon.ml +++ b/src/proto_alpha/lib_tx_rollup/daemon.ml @@ -135,7 +135,7 @@ let extract_messages_from_block block_info rollup_id = (ITransaction_result (Transaction_to_tx_rollup_result {ticket_hash; _})) ) when Tx_rollup.equal dst rollup_id - && Entrypoint.(entrypoint = Tx_rollup.deposit_entrypoint) -> + && Entrypoint.(entrypoint = Entrypoint.deposit) -> (* Deposit message *) ( Option.bind (Data_encoding.force_decode parameters) @@ fun parameters -> 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 01667c16b6b8c3ff37565845ff067a9734e4260f..fdb1311dceae60427abec0eb79c5dc8ef8dd1c50 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 @@ -59,7 +59,8 @@ "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 64467b125187fd1f4bcd46c1fdf1b4176a49366f..f136edd3e518360564a2f1fd510d554f9f2ed88c 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 @@ -59,7 +59,8 @@ "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 29b15e2ad97e9591479d36fcf9ec0470d6884ec6..4cf7d8981c0e454b7beae46e35e9e803bbaa5fe2 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 @@ -59,7 +59,8 @@ "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 3b937e877a92010ba3b23f1f8f32a066c475bae9..bf8b201f62114e4a183c3554ddce335e1782689e 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 @@ -59,7 +59,8 @@ "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 3b937e877a92010ba3b23f1f8f32a066c475bae9..bf8b201f62114e4a183c3554ddce335e1782689e 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 @@ -59,7 +59,8 @@ "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 d9b957180c4d02eefdfcfed7b8d70fa371a3114f..27249b85c280795af6c5e4989fb5b7d386095437 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 @@ -115,7 +115,8 @@ This sequence of operations was run: "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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. @@ -225,7 +226,8 @@ This sequence of operations was run: "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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 48eab618bf3a7de59db0d0cafa27188c89cbbe03..91cdf4b859a3c11d28ec3cbbca1856cf701a6592 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 @@ -115,7 +115,8 @@ This sequence of operations was run: "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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. @@ -225,7 +226,8 @@ This sequence of operations was run: "sc_rollup_number_of_sections_in_dissection": 32, "sc_rollup_timeout_period_in_blocks": 20160, "sc_rollup_max_number_of_cemented_commitments": 5, - "zk_rollup_enable": false, "zk_rollup_min_pending_to_process": 10 } + "zk_rollup_enable": false, "zk_rollup_origination_size": 4000, + "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.