From b730087ce34d51117131137256cc612a733f0f9b Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 24 Jan 2022 11:04:08 -0500 Subject: [PATCH 1/6] Proto,Tx_rollup: Pre-rejections repr and storage Co-author-by: Marigold Co-author-by: Nomadic Labs Co-author-by: Oxhead Alpha --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 2 + src/proto_alpha/lib_protocol/alpha_context.ml | 6 + .../lib_protocol/alpha_context.mli | 45 ++++++ src/proto_alpha/lib_protocol/dune.inc | 10 ++ src/proto_alpha/lib_protocol/storage.ml | 80 +++++++++++ src/proto_alpha/lib_protocol/storage.mli | 67 +++++++++ .../lib_protocol/tx_rollup_errors_repr.ml | 46 +++++- .../lib_protocol/tx_rollup_l2_proof.ml | 5 + .../lib_protocol/tx_rollup_l2_proof.mli | 2 + .../lib_protocol/tx_rollup_rejection_repr.ml | 131 ++++++++++++++++++ .../lib_protocol/tx_rollup_rejection_repr.mli | 51 +++++++ .../tx_rollup_rejection_storage.ml | 128 +++++++++++++++++ .../tx_rollup_rejection_storage.mli | 53 +++++++ 13 files changed, 625 insertions(+), 1 deletion(-) create mode 100644 src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.ml create mode 100644 src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.mli create mode 100644 src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml create mode 100644 src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index d081d208e5a4..38069b788abc 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -62,6 +62,7 @@ "Tx_rollup_message_result_repr", "Tx_rollup_message_result_hash_repr", "Tx_rollup_commitment_repr", + "Tx_rollup_rejection_repr", "Tx_rollup_errors_repr", "Tx_rollup_state_repr", "Bond_id_repr", @@ -128,6 +129,7 @@ "Tx_rollup_state_storage", "Tx_rollup_reveal_storage", "Tx_rollup_inbox_storage", + "Tx_rollup_rejection_storage", "Tx_rollup_commitment_storage", "Tx_rollup_storage", "Sc_rollup_storage", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 520c0f00d71c..1a04b414914c 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -283,6 +283,12 @@ module Tx_rollup_commitment = struct end module Tx_rollup_hash = Tx_rollup_hash_builder + +module Tx_rollup_rejection = struct + include Tx_rollup_rejection_repr + include Tx_rollup_rejection_storage +end + module Tx_rollup_errors = Tx_rollup_errors_repr module Global_constants_storage = Global_constants_storage diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index b806e5f5429f..a7299d151c34 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2046,6 +2046,47 @@ module Tx_rollup_hash : sig (context * Tx_rollup_withdraw_list_hash.t) tzresult end +(** This simply re-exports {!Tx_rollup_rejection_repr}. See + {!Tx_rollup_rejection_repr} for additional documentation of this module. *) +module Tx_rollup_rejection : sig + module Rejection_hash : sig + val rejection_hash : string + + include S.HASH + end + + val generate_prerejection : + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup.t -> + level:Tx_rollup_level.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + Rejection_hash.t + + val prereject : + context -> Tx_rollup.t -> Rejection_hash.t -> context tzresult Lwt.t + + val check_prerejection : + context -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup.t -> + level:Tx_rollup_level.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + (context * int32) tzresult Lwt.t + + val update_accepted_prerejection : + context -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup.t -> + level:Tx_rollup_level.t -> + commitment:Tx_rollup_commitment_hash.t -> + commitment_exists:bool -> + proof:Tx_rollup_l2_proof.t -> + priority:int32 -> + context tzresult Lwt.t +end + module Tx_rollup_errors : sig type error += | Tx_rollup_already_exists of Tx_rollup.t @@ -2115,6 +2156,10 @@ module Tx_rollup_errors : sig provided : Context_hash.t; } | No_withdrawals_to_dispatch + | Rejection_without_prerejection + | Duplicate_prerejection + | Prerejection_without_inbox + | Rejection_for_nonexistent_commitment val check_path_depth : [`Inbox | `Commitment] -> int -> count_limit:int -> unit tzresult diff --git a/src/proto_alpha/lib_protocol/dune.inc b/src/proto_alpha/lib_protocol/dune.inc index 245068049405..b9b3172fec21 100644 --- a/src/proto_alpha/lib_protocol/dune.inc +++ b/src/proto_alpha/lib_protocol/dune.inc @@ -87,6 +87,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_message_result_repr.mli tx_rollup_message_result_repr.ml tx_rollup_message_result_hash_repr.mli tx_rollup_message_result_hash_repr.ml tx_rollup_commitment_repr.mli tx_rollup_commitment_repr.ml + tx_rollup_rejection_repr.mli tx_rollup_rejection_repr.ml tx_rollup_errors_repr.ml tx_rollup_state_repr.mli tx_rollup_state_repr.ml bond_id_repr.mli bond_id_repr.ml @@ -146,6 +147,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_state_storage.mli tx_rollup_state_storage.ml tx_rollup_reveal_storage.mli tx_rollup_reveal_storage.ml tx_rollup_inbox_storage.mli tx_rollup_inbox_storage.ml + tx_rollup_rejection_storage.mli tx_rollup_rejection_storage.ml tx_rollup_commitment_storage.mli tx_rollup_commitment_storage.ml tx_rollup_storage.mli tx_rollup_storage.ml sc_rollup_storage.mli sc_rollup_storage.ml @@ -275,6 +277,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_message_result_repr.mli tx_rollup_message_result_repr.ml tx_rollup_message_result_hash_repr.mli tx_rollup_message_result_hash_repr.ml tx_rollup_commitment_repr.mli tx_rollup_commitment_repr.ml + tx_rollup_rejection_repr.mli tx_rollup_rejection_repr.ml tx_rollup_errors_repr.ml tx_rollup_state_repr.mli tx_rollup_state_repr.ml bond_id_repr.mli bond_id_repr.ml @@ -334,6 +337,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_state_storage.mli tx_rollup_state_storage.ml tx_rollup_reveal_storage.mli tx_rollup_reveal_storage.ml tx_rollup_inbox_storage.mli tx_rollup_inbox_storage.ml + tx_rollup_rejection_storage.mli tx_rollup_rejection_storage.ml tx_rollup_commitment_storage.mli tx_rollup_commitment_storage.ml tx_rollup_storage.mli tx_rollup_storage.ml sc_rollup_storage.mli sc_rollup_storage.ml @@ -463,6 +467,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_message_result_repr.mli tx_rollup_message_result_repr.ml tx_rollup_message_result_hash_repr.mli tx_rollup_message_result_hash_repr.ml tx_rollup_commitment_repr.mli tx_rollup_commitment_repr.ml + tx_rollup_rejection_repr.mli tx_rollup_rejection_repr.ml tx_rollup_errors_repr.ml tx_rollup_state_repr.mli tx_rollup_state_repr.ml bond_id_repr.mli bond_id_repr.ml @@ -522,6 +527,7 @@ module CamlinternalFormatBasics = struct include CamlinternalFormatBasics end tx_rollup_state_storage.mli tx_rollup_state_storage.ml tx_rollup_reveal_storage.mli tx_rollup_reveal_storage.ml tx_rollup_inbox_storage.mli tx_rollup_inbox_storage.ml + tx_rollup_rejection_storage.mli tx_rollup_rejection_storage.ml tx_rollup_commitment_storage.mli tx_rollup_commitment_storage.ml tx_rollup_storage.mli tx_rollup_storage.ml sc_rollup_storage.mli sc_rollup_storage.ml @@ -673,6 +679,7 @@ include Tezos_raw_protocol_alpha.Main Tx_rollup_message_result_repr Tx_rollup_message_result_hash_repr Tx_rollup_commitment_repr + Tx_rollup_rejection_repr Tx_rollup_errors_repr Tx_rollup_state_repr Bond_id_repr @@ -732,6 +739,7 @@ include Tezos_raw_protocol_alpha.Main Tx_rollup_state_storage Tx_rollup_reveal_storage Tx_rollup_inbox_storage + Tx_rollup_rejection_storage Tx_rollup_commitment_storage Tx_rollup_storage Sc_rollup_storage @@ -902,6 +910,7 @@ include Tezos_raw_protocol_alpha.Main tx_rollup_message_result_repr.mli tx_rollup_message_result_repr.ml tx_rollup_message_result_hash_repr.mli tx_rollup_message_result_hash_repr.ml tx_rollup_commitment_repr.mli tx_rollup_commitment_repr.ml + tx_rollup_rejection_repr.mli tx_rollup_rejection_repr.ml tx_rollup_errors_repr.ml tx_rollup_state_repr.mli tx_rollup_state_repr.ml bond_id_repr.mli bond_id_repr.ml @@ -961,6 +970,7 @@ include Tezos_raw_protocol_alpha.Main tx_rollup_state_storage.mli tx_rollup_state_storage.ml tx_rollup_reveal_storage.mli tx_rollup_reveal_storage.ml tx_rollup_inbox_storage.mli tx_rollup_inbox_storage.ml + tx_rollup_rejection_storage.mli tx_rollup_rejection_storage.ml tx_rollup_commitment_storage.mli tx_rollup_commitment_storage.ml tx_rollup_storage.mli tx_rollup_storage.ml sc_rollup_storage.mli sc_rollup_storage.ml diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 68e37758c40e..b2a7525ba0ab 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1443,6 +1443,24 @@ module Tx_rollup = struct end) (Bitset) + module Int32_index = struct + type t = int32 + + let compare = Compare.Int32.compare + + let encoding = Data_encoding.int32 + + let rpc_arg = RPC_arg.int32 + + let path_length = 1 + + let to_path i l = Int32.to_string i :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [i] -> Int32.of_string_opt i + end + module Commitment = Level_context.Make_carbonated_map (struct @@ -1468,6 +1486,68 @@ module Tx_rollup = struct let encoding = Data_encoding.int31 end) + + module Prerejection_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["tx_rollup_prerejection_index"] + end)) + (Make_index (Tx_rollup_rejection_repr.Rejection_hash.Index)) + + module Prerejection = + Prerejection_context.Make_carbonated_map + (struct + let name = ["prerejection"] + end) + (struct + type t = Tx_rollup_repr.t * int32 + + let encoding = + Data_encoding.( + obj2 (req "tx_rollup" Tx_rollup_repr.encoding) (req "index" int32)) + end) + + module Prerejection_counter = + Indexed_context.Make_carbonated_map + (struct + let name = ["prerejection_counter"] + end) + (Encoding.Int32) + + module Prerejections_by_index_context = + Make_subcontext (Registered) (Level_context.Raw_context) + (struct + let name = ["prerejections_by_index"] + end) + + module Prerejections_by_index = + Make_indexed_carbonated_data_storage + (Prerejections_by_index_context) + (Make_index (Int32_index)) + (struct + type t = Tx_rollup_rejection_repr.Rejection_hash.t + + let encoding = Tx_rollup_rejection_repr.Rejection_hash.encoding + end) + + module Accepted_prerejections_context = + Make_subcontext (Registered) (Level_context.Raw_context) + (struct + let name = ["accepted_prerejections"] + end) + + module Accepted_prerejections = struct + include + Make_indexed_carbonated_data_storage + (Accepted_prerejections_context) + (Make_index (Tx_rollup_commitment_repr.Index)) + (struct + type t = Tx_rollup_rejection_repr.prerejection + + let encoding = Tx_rollup_rejection_repr.prerejection_encoding + end) + end end module Sc_rollup = struct diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 940de30ebd4e..9620678d2980 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -654,6 +654,73 @@ module Tx_rollup : sig with type key = Signature.public_key_hash and type value = int and type t := Raw_context.t * Tx_rollup_repr.t + + (** Track prerejections. Before a rejection can be submitted, a + pre-rejection must be submitted by the same contract which will submit + the rejection. A pre-rejection contains a hash of the rejection with + the submitting contract. Regardless of the order in which rejections + are submitted, the first pre-rejection submitted has priority. + This dramatically reduces the incentives for front-running. Here, we + just store the pre-rejections themselves and their priorities, so that + we can quickly check their existence when a rejection is filed.*) + module Prerejection : + Non_iterable_indexed_carbonated_data_storage + with type key = Tx_rollup_rejection_repr.Rejection_hash.t + and type value = Tx_rollup_repr.t * int32 + and type t := Raw_context.t + + (** Prerejections are indexed by a counter which monotonically increases. + Each tx_rollup has its own counter. *) + module Prerejection_counter : + Non_iterable_indexed_carbonated_data_storage + with type key = Tx_rollup_repr.t + and type value = int32 + and type t := Raw_context.t + + (** In order to garbage-collect prerejections, we store them + according to the rollup level at which they were submitted. + This seems strange, but it lets us garbage-collect them during + rollup level finalization, which would otherwise be impossible. + Since we don't know what rollup level they are for, we + cannot use that. *) + module Prerejections_by_index : sig + include + Non_iterable_indexed_carbonated_data_storage + with type key = int32 + and type value = Tx_rollup_rejection_repr.Rejection_hash.t + and type t := + (Raw_context.t * Tx_rollup_repr.t) * Tx_rollup_level_repr.t + + val list_values : + ?offset:int -> + ?length:int -> + (Raw_context.t * Tx_rollup_repr.t) * Tx_rollup_level_repr.t -> + (Raw_context.t * Tx_rollup_rejection_repr.Rejection_hash.t list) tzresult + Lwt.t + end + + (** When the first rejection for a commitment is filed, we put + the corresponding prerejection into this table. The level, + here, is the level that the commitment is for. Later, if + we get any other rejections for the same commitment, and + those rejections have earlier prerejections, we replace + the accepted prerejection here. At finalization time, + for [level], we can credit the contract listed here. *) + module Accepted_prerejections : sig + include + Non_iterable_indexed_carbonated_data_storage + with type key = Tx_rollup_commitment_repr.Hash.t + and type value = Tx_rollup_rejection_repr.prerejection + and type t := + (Raw_context.t * Tx_rollup_repr.t) * Tx_rollup_level_repr.t + + val list_values : + ?offset:int -> + ?length:int -> + (Raw_context.t * Tx_rollup_repr.t) * Tx_rollup_level_repr.t -> + (Raw_context.t * Tx_rollup_rejection_repr.prerejection list) tzresult + Lwt.t + end end module Sc_rollup : sig diff --git a/src/proto_alpha/lib_protocol/tx_rollup_errors_repr.ml b/src/proto_alpha/lib_protocol/tx_rollup_errors_repr.ml index a79f10792ef9..706f9033cc19 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_errors_repr.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_errors_repr.ml @@ -92,6 +92,11 @@ type error += | Proof_produced_rejected_state | Proof_invalid_before of {agreed : Context_hash.t; provided : Context_hash.t} | No_withdrawals_to_dispatch + | Ticket_content_size_limit_exceeded of {content_size : int; limit : int} + | Rejection_without_prerejection + | Duplicate_prerejection + | Prerejection_without_inbox + | Rejection_for_nonexistent_commitment let check_path_depth kind provided ~count_limit = let limit = Merkle_list.max_depth ~count_limit in @@ -664,4 +669,43 @@ let () = ~description:"Cannot dispatch an empty list of withdrawals" empty (function No_withdrawals_to_dispatch -> Some () | _ -> None) - (fun () -> No_withdrawals_to_dispatch) + (fun () -> No_withdrawals_to_dispatch) ; + (* Rejection_without_prerejection *) + register_error_kind + `Temporary + ~id:"tx_rollup_rejection_without_prerejection" + ~title:"This rejection is missing a prerejection" + ~description:"This rejection is missing a prerejection" + unit + (function Rejection_without_prerejection -> Some () | _ -> None) + (fun () -> Rejection_without_prerejection) ; + (* Duplicate_prerejection *) + register_error_kind + `Branch + ~id:"tx_rollup_duplicate_prerejection" + ~title:"This prerejection has already been filed" + ~description:"This prerejection has already been filed" + unit + (function Duplicate_prerejection -> Some () | _ -> None) + (fun () -> Duplicate_prerejection) ; + (* Prerejection_without_inbox *) + register_error_kind + `Temporary + ~id:"tx_rollup_prerejection_without_inbox" + ~title:"Prerejection without inbox" + ~description: + "Since there are no inboxes, there are no commitments, and thus a \ + prerejection is useless" + unit + (function Prerejection_without_inbox -> Some () | _ -> None) + (fun () -> Prerejection_without_inbox) ; + (* Rejection_for_nonexistent_commitment *) + register_error_kind + `Temporary + ~id:"tx_rollup_rejection_for_nonexistent_commitment" + ~title:"Rejection for nonexistent commit" + ~description: + "This rejection rejects a commit that does not and has never existed" + unit + (function Rejection_for_nonexistent_commitment -> Some () | _ -> None) + (fun () -> Rejection_for_nonexistent_commitment) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml index 381001361315..f46f2e0dcda8 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml @@ -27,3 +27,8 @@ type t = Context.Proof.stream Context.Proof.t let encoding = Context.Proof_encoding.V2.Tree2.stream_proof_encoding + +let ( = ) t1 t2 = + let t1_bytes = Data_encoding.Binary.to_bytes_exn encoding t1 in + let t2_bytes = Data_encoding.Binary.to_bytes_exn encoding t2 in + Compare.Bytes.(t1_bytes = t2_bytes) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli index 6085db8214fc..5a241063d0a2 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli @@ -28,3 +28,5 @@ type t = Context.Proof.stream Context.Proof.t val encoding : t Data_encoding.t + +val ( = ) : t -> t -> bool diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.ml b/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.ml new file mode 100644 index 000000000000..9f74b544296e --- /dev/null +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.ml @@ -0,0 +1,131 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Rejection_hash = struct + let rejection_hash = "\001\111\092\025" (* rej1(37) *) + + module H = + Blake2B.Make + (Base58) + (struct + let name = "Rejection_hash" + + let title = "A rejection ID" + + let b58check_prefix = rejection_hash + + let size = Some 20 + end) + + include H + + let () = Base58.check_encoded_prefix b58check_encoding "rej1" 37 + + include Path_encoding.Make_hex (H) + + let rpc_arg = + let construct = Data_encoding.Binary.to_string_exn encoding in + let destruct str = + Option.value_e ~error:"Failed to decode rejection" + @@ Data_encoding.Binary.of_string_opt encoding str + in + RPC_arg.make + ~descr:"A tx_rollup rejection." + ~name:"tx_rollup_rejection" + ~construct + ~destruct + () + + module Index = struct + type nonrec t = t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt encoding) + | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare + end +end + +let generate_prerejection : + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + Rejection_hash.t = + fun ~source ~tx_rollup ~level ~message_position ~proof -> + let to_bytes = Data_encoding.Binary.to_bytes_exn in + let rollup_bytes = to_bytes Tx_rollup_repr.encoding tx_rollup in + let level_bytes = to_bytes Tx_rollup_level_repr.encoding level in + let proof_bytes = + Data_encoding.Binary.to_bytes_exn Tx_rollup_l2_proof.encoding proof + in + let message_position_bytes = to_bytes Data_encoding.int31 message_position in + let contract_bytes = to_bytes Signature.Public_key_hash.encoding source in + Rejection_hash.hash_bytes + [ + rollup_bytes; + level_bytes; + proof_bytes; + message_position_bytes; + contract_bytes; + ] + +type prerejection = { + hash : Tx_rollup_commitment_repr.Hash.t; + proof : Tx_rollup_l2_proof.t; + contract : Signature.Public_key_hash.t; + priority : int32; +} + +let prerejection_encoding = + Data_encoding.( + conv + (fun {hash; contract; priority; proof} -> + (hash, contract, priority, proof)) + (fun (hash, contract, priority, proof) -> + {hash; contract; priority; proof}) + (obj4 + (req "hash" Tx_rollup_commitment_repr.Hash.encoding) + (req "contract" Signature.Public_key_hash.encoding) + (req "priority" int32) + (req "proof" Tx_rollup_l2_proof.encoding))) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.mli b/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.mli new file mode 100644 index 000000000000..d1c01b33a0c2 --- /dev/null +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_repr.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Rejection_hash : sig + val rejection_hash : string + + include S.HASH + + module Index : Storage_description.INDEX with type t = t +end + +val generate_prerejection : + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + Rejection_hash.t + +type prerejection = { + hash : Tx_rollup_commitment_repr.Hash.t; + proof : Tx_rollup_l2_proof.t; + contract : Signature.Public_key_hash.t; + priority : int32; +} + +val prerejection_encoding : prerejection Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml new file mode 100644 index 000000000000..3348dc14be44 --- /dev/null +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml @@ -0,0 +1,128 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tx_rollup_errors_repr + +let prereject : + Raw_context.t -> + Tx_rollup_repr.t -> + Tx_rollup_rejection_repr.Rejection_hash.t -> + Raw_context.t tzresult Lwt.t = + fun ctxt tx_rollup hash -> + Tx_rollup_state_storage.get ctxt tx_rollup >>=? fun (ctxt, state) -> + Lwt.return + @@ Option.value_e + ~error:(Error_monad.trace_of_error Prerejection_without_inbox) + @@ Tx_rollup_state_repr.head_levels state + >>=? fun (level, _) -> + Storage.Tx_rollup.Prerejection.mem ctxt hash >>=? fun (ctxt, is_mem) -> + fail_when is_mem Duplicate_prerejection >>=? fun () -> + (Storage.Tx_rollup.Prerejection_counter.find ctxt tx_rollup >>=? function + | (ctxt, None) -> + Storage.Tx_rollup.Prerejection_counter.init ctxt tx_rollup 1l + >>=? fun (ctxt, _) -> return (ctxt, 0l) + | (ctxt, Some counter) -> + Storage.Tx_rollup.Prerejection_counter.update + ctxt + tx_rollup + (Int32.add counter 1l) + >>=? fun (ctxt, _) -> return (ctxt, counter)) + >>=? fun (ctxt, counter) -> + Storage.Tx_rollup.Prerejection.add ctxt hash (tx_rollup, counter) + >>=? fun (ctxt, _, _) -> + Storage.Tx_rollup.Prerejections_by_index.add + ((ctxt, tx_rollup), level) + counter + hash + >|=? fun (ctxt, _, _) -> ctxt + +let check_prerejection : + Raw_context.t -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + (Raw_context.t * int32) tzresult Lwt.t = + fun ctxt ~source ~tx_rollup ~level ~message_position ~proof -> + let prerejection_hash = + Tx_rollup_rejection_repr.generate_prerejection + ~source + ~tx_rollup + ~level + ~message_position + ~proof + in + Storage.Tx_rollup.Prerejection.find ctxt prerejection_hash + >>=? fun (ctxt, prerejection) -> + match prerejection with + | Some (expected_rollup, priority) + when Tx_rollup_repr.(expected_rollup = tx_rollup) -> + return (ctxt, priority) + | Some _ | None -> fail Rejection_without_prerejection + +let update_accepted_prerejection : + Raw_context.t -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + commitment:Tx_rollup_commitment_repr.Hash.t -> + commitment_exists:bool -> + proof:Tx_rollup_l2_proof.t -> + priority:int32 -> + Raw_context.t tzresult Lwt.t = + fun ctxt + ~source + ~tx_rollup + ~level + ~commitment + ~commitment_exists + ~proof + ~priority -> + (Storage.Tx_rollup.Accepted_prerejections.find + ((ctxt, tx_rollup), level) + commitment + >>=? function + | (ctxt, None) -> + (* The commitment doesn't exist, it wasn't previously rejected. So the + commitment never existed, and this rejection is invalid. *) + fail_unless commitment_exists Rejection_for_nonexistent_commitment + >>=? fun () -> return (ctxt, Int32.max_int, proof) + | (ctxt, Some old) -> return (ctxt, old.priority, old.proof)) + >>=? fun (ctxt, old_priority, old_proof) -> + fail_unless Tx_rollup_l2_proof.(old_proof = proof) Proof_failed_to_reject + >>=? fun () -> + if Compare.Int32.(old_priority <= priority) then return ctxt + else + let new_prerejection : Tx_rollup_rejection_repr.prerejection = + {hash = commitment; contract = source; priority; proof} + in + Storage.Tx_rollup.Accepted_prerejections.add + ((ctxt, tx_rollup), level) + commitment + new_prerejection + >>=? fun (ctxt, _, _) -> return ctxt diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli new file mode 100644 index 000000000000..068b9481cda9 --- /dev/null +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** [prereject ctxt tx_rollup hash] stores a prerejection *) +val prereject : + Raw_context.t -> + Tx_rollup_repr.t -> + Tx_rollup_rejection_repr.Rejection_hash.t -> + Raw_context.t tzresult Lwt.t + +val check_prerejection : + Raw_context.t -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + (Raw_context.t * int32) tzresult Lwt.t + +val update_accepted_prerejection : + Raw_context.t -> + source:Signature.Public_key_hash.t -> + tx_rollup:Tx_rollup_repr.t -> + level:Tx_rollup_level_repr.t -> + commitment:Tx_rollup_commitment_repr.Hash.t -> + commitment_exists:bool -> + proof:Tx_rollup_l2_proof.t -> + priority:int32 -> + Raw_context.t tzresult Lwt.t -- GitLab From 1600a4158f75ab85fd54919ea27203375a98af55 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 3 Jan 2022 16:13:22 -0500 Subject: [PATCH 2/6] Proto,Tx_rollup: Prerejection operation Co-author-by: Marigold Co-author-by: Nomadic Labs Co-author-by: Oxhead Alpha --- .../lib_client/client_proto_context.ml | 3 +- .../lib_client/client_proto_context.mli | 1 + src/proto_alpha/lib_client/injection.ml | 4 + .../lib_client/operation_result.ml | 29 ++ .../client_proto_context_commands.ml | 4 + .../lib_protocol/alpha_context.mli | 22 ++ src/proto_alpha/lib_protocol/apply.ml | 200 +++++----- src/proto_alpha/lib_protocol/apply_results.ml | 67 ++++ .../lib_protocol/apply_results.mli | 4 + .../lib_protocol/operation_repr.ml | 122 +++++-- .../lib_protocol/operation_repr.mli | 14 + .../lib_protocol/test/helpers/block.ml | 6 +- .../lib_protocol/test/helpers/op.ml | 30 +- .../lib_protocol/test/helpers/op.mli | 16 + .../integration/operations/test_tx_rollup.ml | 342 +++++++++++++----- .../tx_rollup_commitment_storage.ml | 14 + .../tx_rollup_commitment_storage.mli | 11 + .../_regressions/rpc/alpha.client.mempool.out | 211 +++++++++++ tezt/_regressions/rpc/alpha.proxy.mempool.out | 211 +++++++++++ 19 files changed, 1091 insertions(+), 220 deletions(-) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index fdbf108f330b..9dd19b6c1e59 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -968,7 +968,7 @@ let submit_tx_rollup_rejection (cctxt : #full) ~chain ~block ?confirmations ?counter ~source ~src_pk ~src_sk ~fee_parameter ~level ~tx_rollup ~message ~message_position ~message_path ~message_result_hash ~message_result_path ~previous_context_hash ~previous_withdraw_list_hash - ~previous_message_result_path ~proof () = + ~previous_message_result_path ~proof ~commitment () = let previous_message_result = Tx_rollup_message_result. { @@ -995,6 +995,7 @@ let submit_tx_rollup_rejection (cctxt : #full) ~chain ~block ?confirmations previous_message_result_path; previous_message_result; proof; + commitment; })) in Injection.inject_manager_operation diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index 6ad41787284f..bc35f7d7c63c 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -573,6 +573,7 @@ val submit_tx_rollup_rejection : previous_withdraw_list_hash:Tx_rollup_withdraw_list_hash.t -> previous_message_result_path:Tx_rollup_commitment.Merkle.path -> proof:Tx_rollup_l2_proof.t -> + commitment:Tx_rollup_commitment_hash.t -> unit -> (Operation_hash.t * Kind.tx_rollup_rejection Kind.manager contents diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 128ba6715bed..c2597ff6d903 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -340,6 +340,8 @@ let estimated_gas_single (type kind) | Applied (Tx_rollup_dispatch_tickets_result {consumed_gas; _}) -> Ok consumed_gas | Applied (Transfer_ticket_result {consumed_gas; _}) -> Ok consumed_gas + | Applied (Tx_rollup_prerejection_result {consumed_gas; _}) -> + Ok consumed_gas | Applied (Sc_rollup_originate_result {consumed_gas; _}) -> Ok consumed_gas | Applied (Sc_rollup_add_messages_result {consumed_gas; _}) -> Ok consumed_gas @@ -397,6 +399,7 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size Ok paid_storage_size_diff | Applied (Transfer_ticket_result {paid_storage_size_diff; _}) -> Ok paid_storage_size_diff + | Applied (Tx_rollup_prerejection_result _) -> Ok Z.zero | Applied (Sc_rollup_originate_result {size; _}) -> Ok size | Applied (Sc_rollup_add_messages_result _) -> Ok Z.zero (* The following Sc_rollup operations have zero storage cost because we @@ -466,6 +469,7 @@ let originated_contracts_single (type kind) | Applied (Tx_rollup_rejection_result _) -> Ok [] | Applied (Tx_rollup_dispatch_tickets_result _) -> Ok [] | Applied (Transfer_ticket_result _) -> Ok [] + | Applied (Tx_rollup_prerejection_result _) -> Ok [] | Applied (Sc_rollup_originate_result _) -> Ok [] | Applied (Sc_rollup_add_messages_result _) -> Ok [] | Applied (Sc_rollup_cement_result _) -> Ok [] diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 9b307d950be3..212b7565da72 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -270,6 +270,20 @@ let pp_manager_operation_content (type kind) source internal pp_result ppf source pp_result result + | Tx_rollup_prerejection {tx_rollup; hash} -> + Format.fprintf + ppf + "@[%s:tx_rollup %a hash %a @,From: %a%a@]" + (if internal then "Internal tx rollup prerejection" + else "Tx rollup rejection") + Tx_rollup.pp + tx_rollup + Tx_rollup_rejection.Rejection_hash.pp + hash + Contract.pp + source + pp_result + result | Sc_rollup_originate {kind; boot_sector} -> let (module R : Sc_rollups.PVM.S) = Sc_rollups.of_kind kind in Format.fprintf @@ -639,6 +653,10 @@ let pp_manager_operation_contents_and_result ppf Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas ; pp_balance_updates_opt ppf balance_updates in + let pp_tx_rollup_prerejection_result + (Tx_rollup_prerejection_result {consumed_gas}) = + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + in let pp_sc_rollup_originate_result (Sc_rollup_originate_result {address; consumed_gas; size; balance_updates}) = @@ -826,6 +844,17 @@ let pp_manager_operation_contents_and_result ppf "@[This transfer ticket operation was BACKTRACKED, its expected \ effects (as follow) were NOT applied.@]" ; pp_transfer_ticket_result op + | Applied (Tx_rollup_prerejection_result _ as op) -> + Format.fprintf + ppf + "This tx rollup prerejection operation was successfully applied" ; + pp_tx_rollup_prerejection_result op + | Backtracked ((Tx_rollup_prerejection_result _ as op), _err) -> + Format.fprintf + ppf + "@[This tx rollup prerejection operation was BACKTRACKED, its \ + expected effects (as follow) were NOT applied.@]" ; + pp_tx_rollup_prerejection_result op | Applied (Sc_rollup_originate_result _ as op) -> Format.fprintf ppf diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index 8d2c21be3dcf..ba2e53a61350 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -2672,6 +2672,8 @@ let commands_rw () = @@ Tx_rollup.proof_param ~usage: "Proof that the disputed message result provided is incorrect." + @@ prefix "with" @@ prefix "commitment" + @@ Tx_rollup.commitment_hash_param ~usage:"The commitment being rejected" @@ prefix "from" @@ ContractAlias.destination_param ~name:"src" @@ -2700,6 +2702,7 @@ let commands_rw () = previous_withdraw_list_hash previous_message_result_path proof + commitment (_, source) cctxt -> match Contract.is_implicit source with @@ -2745,6 +2748,7 @@ let commands_rw () = ~previous_context_hash ~previous_withdraw_list_hash ~previous_message_result_path + ~commitment () >>=? fun _res -> return_unit); command diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index a7299d151c34..3e19ee95dcdd 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2027,6 +2027,14 @@ module Tx_rollup_commitment : sig Tx_rollup_state.t -> Tx_rollup_level.t -> (context * Tx_rollup_state.t) tzresult Lwt.t + + val commitment_exists : + context -> + Tx_rollup.t -> + Tx_rollup_state.t -> + Tx_rollup_level.t -> + Tx_rollup_commitment_hash.t -> + (context * bool) tzresult Lwt.t end module Tx_rollup_hash : sig @@ -2865,6 +2873,8 @@ module Kind : sig type transfer_ticket = Transfer_ticket_kind + type tx_rollup_prerejection = Tx_rollup_prerejection_kind + type sc_rollup_originate = Sc_rollup_originate_kind type sc_rollup_add_messages = Sc_rollup_add_messages_kind @@ -2892,6 +2902,7 @@ module Kind : sig | Tx_rollup_dispatch_tickets_manager_kind : tx_rollup_dispatch_tickets manager | Transfer_ticket_manager_kind : transfer_ticket manager + | Tx_rollup_prerejection_manager_kind : tx_rollup_prerejection manager | Sc_rollup_originate_manager_kind : sc_rollup_originate manager | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager | Sc_rollup_cement_manager_kind : sc_rollup_cement manager @@ -3049,6 +3060,7 @@ and _ manager_operation = previous_message_result : Tx_rollup_message_result.t; previous_message_result_path : Tx_rollup_commitment.Merkle.path; proof : Tx_rollup_l2_proof.t; + commitment : Tx_rollup_commitment_hash.t; } -> Kind.tx_rollup_rejection manager_operation | Tx_rollup_dispatch_tickets : { @@ -3069,6 +3081,11 @@ and _ manager_operation = entrypoint : Entrypoint.t; } -> Kind.transfer_ticket manager_operation + | Tx_rollup_prerejection : { + tx_rollup : Tx_rollup.t; + hash : Tx_rollup_rejection.Rejection_hash.t; + } + -> Kind.tx_rollup_prerejection manager_operation | Sc_rollup_originate : { kind : Sc_rollup.Kind.t; boot_sector : string; @@ -3236,6 +3253,9 @@ module Operation : sig val transfer_ticket_case : Kind.transfer_ticket Kind.manager case + val tx_rollup_prerejection_case : + Kind.tx_rollup_prerejection Kind.manager case + val register_global_constant_case : Kind.register_global_constant Kind.manager case @@ -3300,6 +3320,8 @@ module Operation : sig val transfer_ticket_case : Kind.transfer_ticket case + val tx_rollup_prerejection_case : Kind.tx_rollup_prerejection case + val sc_rollup_originate_case : Kind.sc_rollup_originate case val sc_rollup_add_messages_case : Kind.sc_rollup_add_messages case diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index b3caabbcb873..7ce1ba5c31d0 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1658,91 +1658,117 @@ let apply_external_manager_operation_content : message_result_path; previous_message_result; previous_message_result_path; + commitment = commitment_hash; } -> + Tx_rollup_rejection.check_prerejection + ctxt + ~source + ~tx_rollup + ~level + ~message_position + ~proof + >>=? fun (ctxt, priority) -> Tx_rollup_state.get ctxt tx_rollup >>=? fun (ctxt, state) -> - (* Check [level] *) - Tx_rollup_state.check_level_can_be_rejected state level >>?= fun () -> - Tx_rollup_commitment.get ctxt tx_rollup state level + Tx_rollup_commitment.find ctxt tx_rollup state level >>=? fun (ctxt, commitment) -> - (* Check [message] *) - error_when - Compare.Int.( - message_position < 0 - || commitment.commitment.messages.count <= message_position) - (Tx_rollup_errors.Wrong_message_position - { - level = commitment.commitment.level; - position = message_position; - length = commitment.commitment.messages.count; - }) - >>?= fun () -> - Tx_rollup_inbox.check_message_hash - ctxt - level - tx_rollup - ~position:message_position - message - message_path - >>=? fun ctxt -> - (* Check message result paths *) - Tx_rollup_commitment.check_agreed_and_disputed_results - ctxt - tx_rollup - state - commitment - ~agreed_result:previous_message_result - ~agreed_result_path:previous_message_result_path - ~disputed_result:message_result_hash - ~disputed_result_path:message_result_path - ~disputed_position:message_position - >>=? fun ctxt -> - (* Check [proof] *) - let parameters = - Tx_rollup_l2_apply. - { - tx_rollup_max_withdrawals_per_batch = - Constants.tx_rollup_max_withdrawals_per_batch ctxt; - } - in - Tx_rollup_l2_verifier.verify_proof - ctxt - parameters - message - proof - ~agreed:previous_message_result - ~rejected:message_result_hash - ~max_proof_size: - (Alpha_context.Constants.tx_rollup_rejection_max_proof_size ctxt) - >>=? fun ctxt -> - (* Proof is correct, removing *) - Tx_rollup_commitment.reject_commitment ctxt tx_rollup state level - >>=? fun (ctxt, state) -> - (* Bond slashing, and removing *) - Tx_rollup_commitment.slash_bond ctxt tx_rollup commitment.committer - >>=? fun (ctxt, slashed) -> - (if slashed then - let committer = Contract.implicit_contract commitment.committer in - let bid = Bond_id.Tx_rollup_bond_id tx_rollup in - Token.balance ctxt (`Frozen_bonds (committer, bid)) - >>=? fun (ctxt, burn) -> - Tez.(burn /? 2L) >>?= fun reward -> - Token.transfer - ctxt - (`Frozen_bonds (committer, bid)) - `Tx_rollup_rejection_punishments - burn - >>=? fun (ctxt, burn_update) -> - Token.transfer - ctxt - `Tx_rollup_rejection_rewards - (`Contract source_contract) - reward - >>=? fun (ctxt, reward_update) -> - return (ctxt, burn_update @ reward_update) - else return (ctxt, [])) + (match commitment with + | Some commitment -> + (* Check [level] *) + Tx_rollup_state.check_level_can_be_rejected state level >>?= fun () -> + (* Check [message] *) + error_when + Compare.Int.( + message_position < 0 + || commitment.commitment.messages.count <= message_position) + (Tx_rollup_errors.Wrong_message_position + { + level = commitment.commitment.level; + position = message_position; + length = commitment.commitment.messages.count; + }) + >>?= fun () -> + Tx_rollup_inbox.check_message_hash + ctxt + level + tx_rollup + ~position:message_position + message + message_path + >>=? fun ctxt -> + (* Check message result paths *) + Tx_rollup_commitment.check_agreed_and_disputed_results + ctxt + tx_rollup + state + commitment + ~agreed_result:previous_message_result + ~agreed_result_path:previous_message_result_path + ~disputed_result:message_result_hash + ~disputed_result_path:message_result_path + ~disputed_position:message_position + >>=? fun ctxt -> + (* Check [proof] *) + let parameters = + Tx_rollup_l2_apply. + { + tx_rollup_max_withdrawals_per_batch = + Constants.tx_rollup_max_withdrawals_per_batch ctxt; + } + in + Tx_rollup_l2_verifier.verify_proof + ctxt + parameters + message + proof + ~agreed:previous_message_result + ~rejected:message_result_hash + ~max_proof_size: + (Alpha_context.Constants.tx_rollup_rejection_max_proof_size ctxt) + >>=? fun ctxt -> + (* Proof is correct, removing *) + Tx_rollup_commitment.reject_commitment ctxt tx_rollup state level + >>=? fun (ctxt, state) -> + (* Bond slashing, and removing *) + Tx_rollup_commitment.slash_bond ctxt tx_rollup commitment.committer + >>=? fun (ctxt, slashed) -> + (if slashed then + let committer = Contract.implicit_contract commitment.committer in + let bid = Bond_id.Tx_rollup_bond_id tx_rollup in + Token.balance ctxt (`Frozen_bonds (committer, bid)) + >>=? fun (ctxt, burn) -> + Token.transfer + ctxt + (`Frozen_bonds (committer, bid)) + `Tx_rollup_rejection_punishments + burn + >>=? fun (ctxt, reward_update) -> return (ctxt, reward_update) + else return (ctxt, [])) + >>=? fun (ctxt, balance_updates) -> + Tx_rollup_rejection.update_accepted_prerejection + ctxt + ~source + ~tx_rollup + ~level + ~commitment:commitment_hash + ~commitment_exists:true + ~proof + ~priority + >>=? fun ctxt -> + (* Update state and conclude *) + Tx_rollup_state.update ctxt tx_rollup state >|=? fun ctxt -> + (ctxt, balance_updates) + | None -> + Tx_rollup_rejection.update_accepted_prerejection + ctxt + ~source + ~tx_rollup + ~level + ~commitment:commitment_hash + ~commitment_exists:false + ~proof + ~priority + >>=? fun ctxt -> return (ctxt, [])) >>=? fun (ctxt, balance_updates) -> - (* Update state and conclude *) - Tx_rollup_state.update ctxt tx_rollup state >>=? fun ctxt -> let result = Tx_rollup_rejection_result { @@ -1751,6 +1777,13 @@ let apply_external_manager_operation_content : } in return (ctxt, result, []) + | Tx_rollup_prerejection {tx_rollup; hash} -> + Tx_rollup_rejection.prereject ctxt tx_rollup hash >>=? fun ctxt -> + let result = + Tx_rollup_prerejection_result + {consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt} + in + return (ctxt, result, []) | Sc_rollup_originate {kind; boot_sector} -> Sc_rollup_operations.originate ctxt ~kind ~boot_sector >>=? fun ({address; size}, ctxt) -> @@ -1912,7 +1945,8 @@ let precheck_manager_contents (type kind) ctxt (op : kind Kind.manager contents) Tx_rollup_errors.Message_size_exceeds_limit >>=? fun () -> return ctxt | Tx_rollup_commit _ | Tx_rollup_return_bond _ - | Tx_rollup_finalize_commitment _ | Tx_rollup_remove_commitment _ -> + | Tx_rollup_finalize_commitment _ | Tx_rollup_remove_commitment _ + | Tx_rollup_prerejection _ -> assert_tx_rollup_feature_enabled ctxt >>=? fun () -> return ctxt | Transfer_ticket {contents; ty; _} -> assert_tx_rollup_feature_enabled ctxt >>=? fun () -> @@ -2092,7 +2126,7 @@ let burn_storage_fees : Tx_rollup_origination_result {payload with balance_updates} ) | Tx_rollup_return_bond_result _ | Tx_rollup_remove_commitment_result _ | Tx_rollup_rejection_result _ | Tx_rollup_finalize_commitment_result _ - | Tx_rollup_commit_result _ -> + | Tx_rollup_commit_result _ | Tx_rollup_prerejection_result _ -> return (ctxt, storage_limit, smopr) | Transfer_ticket_result payload -> let consumed = payload.paid_storage_size_diff in diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index 065e5d6c4f0c..b34c7d5ada20 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -194,6 +194,10 @@ type _ successful_manager_operation_result = paid_storage_size_diff : Z.t; } -> Kind.transfer_ticket successful_manager_operation_result + | Tx_rollup_prerejection_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.tx_rollup_prerejection successful_manager_operation_result | Sc_rollup_originate_result : { balance_updates : Receipt.balance_updates; address : Sc_rollup.Address.t; @@ -850,6 +854,26 @@ module Manager_result = struct paid_storage_size_diff; }) + let[@coq_axiom_with_reason "gadt"] tx_rollup_prerejection_case = + make + ~op_case:Operation.Encoding.Manager_operations.tx_rollup_prerejection_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~kind:Kind.Tx_rollup_prerejection_manager_kind + ~select:(function + | Successful_manager_result (Tx_rollup_prerejection_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Tx_rollup_prerejection_result {consumed_gas} -> + (Gas.Arith.ceil consumed_gas, consumed_gas)) + ~inj:(fun (consumed_gas, consumed_milligas) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + Tx_rollup_prerejection_result {consumed_gas = consumed_milligas}) + let[@coq_axiom_with_reason "gadt"] sc_rollup_originate_case = make ~op_case:Operation.Encoding.Manager_operations.sc_rollup_originate_case @@ -1244,6 +1268,10 @@ let equal_manager_kind : | (Kind.Transfer_ticket_manager_kind, Kind.Transfer_ticket_manager_kind) -> Some Eq | (Kind.Transfer_ticket_manager_kind, _) -> None + | ( Kind.Tx_rollup_prerejection_manager_kind, + Kind.Tx_rollup_prerejection_manager_kind ) -> + Some Eq + | (Kind.Tx_rollup_prerejection_manager_kind, _) -> None | ( Kind.Sc_rollup_originate_manager_kind, Kind.Sc_rollup_originate_manager_kind ) -> Some Eq @@ -1712,6 +1740,17 @@ module Encoding = struct Some (op, res) | _ -> None) + let[@coq_axiom_with_reason "gadt"] tx_rollup_prerejection_case = + make_manager_case + Operation.Encoding.tx_rollup_prerejection_case + Manager_result.tx_rollup_prerejection_case + (function + | Contents_and_result + ( (Manager_operation {operation = Tx_rollup_prerejection _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + let[@coq_axiom_with_reason "gadt"] sc_rollup_originate_case = make_manager_case Operation.Encoding.sc_rollup_originate_case @@ -1800,6 +1839,7 @@ let contents_result_encoding = make tx_rollup_rejection_case; make tx_rollup_dispatch_tickets_case; make transfer_ticket_case; + make tx_rollup_prerejection_case; make sc_rollup_originate_case; make sc_rollup_add_messages_case; make sc_rollup_cement_case; @@ -1854,6 +1894,7 @@ let contents_and_result_encoding = make tx_rollup_rejection_case; make transfer_ticket_case; make tx_rollup_dispatch_tickets_case; + make tx_rollup_prerejection_case; make sc_rollup_originate_case; make sc_rollup_add_messages_case; make sc_rollup_cement_case; @@ -2384,6 +2425,32 @@ let kind_equal : } ) -> Some Eq | (Manager_operation {operation = Transfer_ticket _; _}, _) -> None + | ( Manager_operation {operation = Tx_rollup_prerejection _; _}, + Manager_operation_result + {operation_result = Applied (Tx_rollup_prerejection_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Tx_rollup_prerejection _; _}, + Manager_operation_result + {operation_result = Backtracked (Tx_rollup_prerejection_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Tx_rollup_prerejection _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Tx_rollup_prerejection_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Tx_rollup_prerejection _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Tx_rollup_prerejection_manager_kind; + _; + } ) -> + Some Eq + | (Manager_operation {operation = Tx_rollup_prerejection _; _}, _) -> None | ( Manager_operation {operation = Sc_rollup_originate _; _}, Manager_operation_result {operation_result = Applied (Sc_rollup_originate_result _); _} ) -> diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index cea567bab634..c8555b3ba9a0 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -250,6 +250,10 @@ and _ successful_manager_operation_result = paid_storage_size_diff : Z.t; } -> Kind.transfer_ticket successful_manager_operation_result + | Tx_rollup_prerejection_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.tx_rollup_prerejection successful_manager_operation_result | Sc_rollup_originate_result : { balance_updates : Receipt.balance_updates; address : Sc_rollup.Address.t; diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index dec9abba76d0..fec265461195 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -89,6 +89,8 @@ module Kind = struct type transfer_ticket = Transfer_ticket_kind + type tx_rollup_prerejection = Tx_rollup_prerejection_kind + type sc_rollup_originate = Sc_rollup_originate_kind type sc_rollup_add_messages = Sc_rollup_add_messages_kind @@ -116,6 +118,7 @@ module Kind = struct | Tx_rollup_dispatch_tickets_manager_kind : tx_rollup_dispatch_tickets manager | Transfer_ticket_manager_kind : transfer_ticket manager + | Tx_rollup_prerejection_manager_kind : tx_rollup_prerejection manager | Sc_rollup_originate_manager_kind : sc_rollup_originate manager | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager | Sc_rollup_cement_manager_kind : sc_rollup_cement manager @@ -333,6 +336,7 @@ and _ manager_operation = previous_message_result : Tx_rollup_message_result_repr.t; previous_message_result_path : Tx_rollup_commitment_repr.Merkle.path; proof : Tx_rollup_l2_proof.t; + commitment : Tx_rollup_commitment_repr.Hash.t; } -> Kind.tx_rollup_rejection manager_operation | Tx_rollup_dispatch_tickets : { @@ -353,6 +357,11 @@ and _ manager_operation = entrypoint : Entrypoint_repr.t; } -> Kind.transfer_ticket manager_operation + | Tx_rollup_prerejection : { + tx_rollup : Tx_rollup_repr.t; + hash : Tx_rollup_rejection_repr.Rejection_hash.t; + } + -> Kind.tx_rollup_prerejection manager_operation | Sc_rollup_originate : { kind : Sc_rollup_repr.Kind.t; boot_sector : string; @@ -395,6 +404,7 @@ let manager_kind : type kind. kind manager_operation -> kind Kind.manager = | Tx_rollup_rejection _ -> Kind.Tx_rollup_rejection_manager_kind | Tx_rollup_dispatch_tickets _ -> Kind.Tx_rollup_dispatch_tickets_manager_kind | Transfer_ticket _ -> Kind.Transfer_ticket_manager_kind + | Tx_rollup_prerejection _ -> Kind.Tx_rollup_prerejection_manager_kind | Sc_rollup_originate _ -> Kind.Sc_rollup_originate_manager_kind | Sc_rollup_add_messages _ -> Kind.Sc_rollup_add_messages_manager_kind | Sc_rollup_cement _ -> Kind.Sc_rollup_cement_manager_kind @@ -472,6 +482,8 @@ let tx_rollup_operation_dispatch_tickets_tag = let transfer_ticket_tag = tx_rollup_operation_tag_offset + 8 +let tx_rollup_operation_prerejection_tag = tx_rollup_operation_tag_offset + 9 + let sc_rollup_operation_tag_offset = 200 let sc_rollup_operation_origination_tag = sc_rollup_operation_tag_offset + 0 @@ -729,25 +741,28 @@ module Encoding = struct tag = tx_rollup_operation_rejection_tag; name = "tx_rollup_rejection"; encoding = - obj10 - (req "rollup" Tx_rollup_repr.encoding) - (req "level" Tx_rollup_level_repr.encoding) - (req "message" Tx_rollup_message_repr.encoding) - (req "message_position" n) - (req "message_path" Tx_rollup_inbox_repr.Merkle.path_encoding) - (req - "message_result_hash" - Tx_rollup_message_result_hash_repr.encoding) - (req - "message_result_path" - Tx_rollup_commitment_repr.Merkle.path_encoding) - (req - "previous_message_result" - Tx_rollup_message_result_repr.encoding) - (req - "previous_message_result_path" - Tx_rollup_commitment_repr.Merkle.path_encoding) - (req "proof" Tx_rollup_l2_proof.encoding); + merge_objs + (obj9 + (req "rollup" Tx_rollup_repr.encoding) + (req "level" Tx_rollup_level_repr.encoding) + (req "message" Tx_rollup_message_repr.encoding) + (req "message_position" n) + (req "message_path" Tx_rollup_inbox_repr.Merkle.path_encoding) + (req + "message_result_hash" + Tx_rollup_message_result_hash_repr.encoding) + (req + "message_result_path" + Tx_rollup_commitment_repr.Merkle.path_encoding) + (req + "previous_message_result" + Tx_rollup_message_result_repr.encoding) + (req + "previous_message_result_path" + Tx_rollup_commitment_repr.Merkle.path_encoding)) + (obj2 + (req "proof" Tx_rollup_l2_proof.encoding) + (req "commitment" Tx_rollup_commitment_repr.Hash.encoding)); select = (function | Manager (Tx_rollup_rejection _ as op) -> Some op | _ -> None); @@ -765,28 +780,29 @@ module Encoding = struct previous_message_result; previous_message_result_path; proof; + commitment; } -> - ( tx_rollup, - level, - message, - Z.of_int message_position, - message_path, - message_result_hash, - message_result_path, - previous_message_result, - previous_message_result_path, - proof )); + ( ( tx_rollup, + level, + message, + Z.of_int message_position, + message_path, + message_result_hash, + message_result_path, + previous_message_result, + previous_message_result_path ), + (proof, commitment) )); inj = - (fun ( tx_rollup, - level, - message, - message_position, - message_path, - message_result_hash, - message_result_path, - previous_message_result, - previous_message_result_path, - proof ) -> + (fun ( ( tx_rollup, + level, + message, + message_position, + message_path, + message_result_hash, + message_result_path, + previous_message_result, + previous_message_result_path ), + (proof, commitment) ) -> Tx_rollup_rejection { tx_rollup; @@ -799,6 +815,7 @@ module Encoding = struct previous_message_result; previous_message_result_path; proof; + commitment; }); } @@ -885,6 +902,25 @@ module Encoding = struct {contents; ty; ticketer; amount; destination; entrypoint}); } + let[@coq_axiom_with_reason "gadt"] tx_rollup_prerejection_case = + MCase + { + tag = tx_rollup_operation_prerejection_tag; + name = "tx_rollup_prerejection"; + encoding = + obj2 + (req "tx_rollup" Tx_rollup_repr.encoding) + (req "hash" Tx_rollup_rejection_repr.Rejection_hash.encoding); + select = + (function + | Manager (Tx_rollup_prerejection _ as op) -> Some op | _ -> None); + proj = + (function + | Tx_rollup_prerejection {tx_rollup; hash} -> (tx_rollup, hash)); + inj = + (fun (tx_rollup, hash) -> Tx_rollup_prerejection {tx_rollup; hash}); + } + let[@coq_axiom_with_reason "gadt"] sc_rollup_originate_case = MCase { @@ -1301,6 +1337,11 @@ module Encoding = struct transfer_ticket_tag Manager_operations.transfer_ticket_case + let tx_rollup_prerejection_case = + make_manager_case + tx_rollup_operation_prerejection_tag + Manager_operations.tx_rollup_prerejection_case + let sc_rollup_originate_case = make_manager_case sc_rollup_operation_origination_tag @@ -1358,6 +1399,7 @@ module Encoding = struct make tx_rollup_rejection_case; make tx_rollup_dispatch_tickets_case; make transfer_ticket_case; + make tx_rollup_prerejection_case; make sc_rollup_originate_case; make sc_rollup_add_messages_case; make sc_rollup_cement_case; @@ -1567,6 +1609,8 @@ let equal_manager_operation_kind : | (Tx_rollup_dispatch_tickets _, _) -> None | (Transfer_ticket _, Transfer_ticket _) -> Some Eq | (Transfer_ticket _, _) -> None + | (Tx_rollup_prerejection _, Tx_rollup_prerejection _) -> Some Eq + | (Tx_rollup_prerejection _, _) -> None | (Sc_rollup_originate _, Sc_rollup_originate _) -> Some Eq | (Sc_rollup_originate _, _) -> None | (Sc_rollup_add_messages _, Sc_rollup_add_messages _) -> Some Eq diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index de7e706f444b..425127f35a0b 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -118,6 +118,8 @@ module Kind : sig type transfer_ticket = Transfer_ticket_kind + type tx_rollup_prerejection = Tx_rollup_prerejection_kind + type sc_rollup_originate = Sc_rollup_originate_kind type sc_rollup_add_messages = Sc_rollup_add_messages_kind @@ -145,6 +147,7 @@ module Kind : sig | Tx_rollup_dispatch_tickets_manager_kind : tx_rollup_dispatch_tickets manager | Transfer_ticket_manager_kind : transfer_ticket manager + | Tx_rollup_prerejection_manager_kind : tx_rollup_prerejection manager | Sc_rollup_originate_manager_kind : sc_rollup_originate manager | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager | Sc_rollup_cement_manager_kind : sc_rollup_cement manager @@ -379,6 +382,7 @@ and _ manager_operation = previous_message_result : Tx_rollup_message_result_repr.t; previous_message_result_path : Tx_rollup_commitment_repr.Merkle.path; proof : Tx_rollup_l2_proof.t; + commitment : Tx_rollup_commitment_repr.Hash.t; } -> Kind.tx_rollup_rejection manager_operation | Tx_rollup_dispatch_tickets : { @@ -417,6 +421,11 @@ and _ manager_operation = (** The entrypoint of the smart contract address that should receive the tickets. *) } -> Kind.transfer_ticket manager_operation + | Tx_rollup_prerejection : { + tx_rollup : Tx_rollup_repr.t; + hash : Tx_rollup_rejection_repr.Rejection_hash.t; + } + -> Kind.tx_rollup_prerejection manager_operation (* [Sc_rollup_originate] allows an implicit account to originate a new smart contract rollup (initialized with a given boot sector). *) @@ -574,6 +583,9 @@ module Encoding : sig val transfer_ticket_case : Kind.transfer_ticket Kind.manager case + val tx_rollup_prerejection_case : + Kind.tx_rollup_prerejection Kind.manager case + val sc_rollup_originate_case : Kind.sc_rollup_originate Kind.manager case val sc_rollup_add_messages_case : @@ -632,6 +644,8 @@ module Encoding : sig val transfer_ticket_case : Kind.transfer_ticket case + val tx_rollup_prerejection_case : Kind.tx_rollup_prerejection case + val sc_rollup_originate_case : Kind.sc_rollup_originate case val sc_rollup_add_messages_case : Kind.sc_rollup_add_messages case diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index a0dacf2fbce4..77c604d57eb5 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -724,8 +724,9 @@ let bake_n_with_all_balance_updates ?(baking_mode = Application) ?policy | Tx_rollup_remove_commitment_result _ | Tx_rollup_rejection_result _ | Transfer_ticket_result _ | Tx_rollup_dispatch_tickets_result _ - | Sc_rollup_originate_result _ | Sc_rollup_add_messages_result _ - | Sc_rollup_cement_result _ | Sc_rollup_publish_result _ -> + | Tx_rollup_prerejection_result _ | Sc_rollup_originate_result _ + | Sc_rollup_add_messages_result _ | Sc_rollup_cement_result _ + | Sc_rollup_publish_result _ -> balance_updates_rev | Transaction_result (Transaction_to_contract_result {balance_updates; _}) @@ -765,6 +766,7 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = | Successful_manager_result (Tx_rollup_rejection_result _) | Successful_manager_result (Tx_rollup_dispatch_tickets_result _) | Successful_manager_result (Transfer_ticket_result _) + | Successful_manager_result (Tx_rollup_prerejection_result _) | Successful_manager_result (Sc_rollup_originate_result _) | Successful_manager_result (Sc_rollup_add_messages_result _) | Successful_manager_result (Sc_rollup_cement_result _) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index efd574bc1567..1c56f83b77ed 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -639,7 +639,7 @@ let tx_rollup_reject ?counter ?fee ?gas_limit ?storage_limit ctxt ~(message_path : Tx_rollup_inbox.Merkle.path) ~message_result_hash ~message_result_path ~(proof : Tx_rollup_l2_proof.t) ~(previous_message_result : Tx_rollup_message_result.t) - ~previous_message_result_path = + ~previous_message_result_path ~(commitment : Tx_rollup_commitment_hash.t) = manager_operation ?counter ?fee @@ -659,11 +659,39 @@ let tx_rollup_reject ?counter ?fee ?gas_limit ?storage_limit ctxt previous_message_result; previous_message_result_path; message_result_path; + commitment; }) >>=? fun to_sign_op -> Context.Contract.manager ctxt source >|=? fun account -> sign account.sk ctxt to_sign_op +let tx_rollup_prereject ?counter ?fee ?gas_limit ?storage_limit ctxt + ~(source : Contract.t) ~(tx_rollup : Tx_rollup.t) + ~(level : Tx_rollup_level.t) ~(message_position : int) + ~(proof : Tx_rollup_l2_proof.t) = + match Contract.is_implicit source with + | None -> failwith "Expected an implicit contract" + | Some key -> + let hash = + Tx_rollup_rejection.generate_prerejection + ~source:key + ~tx_rollup + ~level + ~message_position + ~proof + in + manager_operation + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + (Tx_rollup_prerejection {tx_rollup; hash}) + >>=? fun to_sign_op -> + Context.Contract.manager ctxt source >|=? fun account -> + sign account.sk ctxt to_sign_op + let originated_sc_rollup op = let packed = Operation.hash_packed op in let nonce = Origination_nonce.Internal_for_tests.initial packed in diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index ef2354bd5a1b..0d710647d76a 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -338,6 +338,21 @@ val transfer_ticket : Entrypoint_repr.t -> (packed_operation, tztrace) result Lwt.t +(** [tx_rollup_prereject ctxt source tx_rollup level hash batch_index] + creates a prerejection to prepare for a rejection. *) +val tx_rollup_prereject : + ?counter:counter -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:counter -> + Context.t -> + source:Contract.t -> + tx_rollup:Tx_rollup.t -> + level:Tx_rollup_level.t -> + message_position:int -> + proof:Tx_rollup_l2_proof.t -> + (packed_operation, tztrace) result Lwt.t + (** [tx_rollup_reject ctxt source tx_rollup tx_rollup level message index proof] Rejects a tx rollup commitment. *) val tx_rollup_reject : @@ -357,6 +372,7 @@ val tx_rollup_reject : proof:Tx_rollup_l2_proof.t -> previous_message_result:Tx_rollup_message_result.t -> previous_message_result_path:Tx_rollup_commitment.Merkle.path -> + commitment:Tx_rollup_commitment_hash.t -> Operation.packed tzresult Lwt.t (** [sc_rollup_origination ctxt source kind boot_sector] originates a new diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml index e6a69322c4d7..4999a35c0790 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml @@ -2347,6 +2347,57 @@ module Rejection = struct replace_commitment ~l2_parameters ~commitment ~store messages >>= fun commitment -> return commitment + let make_rejection_param (commitment : Tx_rollup_commitment.Full.t) ~index = + let message_result_hash = + WithExceptions.Option.get + ~loc:__LOC__ + (List.nth commitment.messages index) + in + let tree = + List.fold_left + (fun tree m -> Tx_rollup_commitment.Merkle.snoc tree m) + Tx_rollup_commitment.Merkle.nil + commitment.messages + in + let path = + match Tx_rollup_commitment.Merkle.compute_path tree index with + | Ok x -> x + | Error _ -> assert false + in + (message_result_hash, path) + + let reject_with_valid_prerejection b contract tx_rollup level message + ~message_position ~message_path ~message_result_hash ~message_result_path + ~proof ~previous_message_result ~previous_message_result_path ~commitment + = + Op.tx_rollup_prereject + (B b) + ~source:contract + ~tx_rollup + ~level + ~message_position + ~proof + >>=? fun operation -> + Block.bake b ~operation >>=? fun b -> + let commitment = + Tx_rollup_commitment.(Compact.hash @@ Full.compact commitment) + in + Op.tx_rollup_reject + (B b) + contract + tx_rollup + level + message + ~message_position + ~message_path + ~message_result_hash + ~message_result_path + ~proof + ~previous_message_result + ~previous_message_result_path + ~commitment + >|=? fun op -> (op, b) + let init_with_deposit ?tx_rollup_hard_size_limit_per_message addr = init_l2_store () >>= fun store -> context_init2 ?tx_rollup_hard_size_limit_per_message () @@ -2373,13 +2424,12 @@ module Rejection = struct test. *) l2_parameters (I i) >>=? fun l2_parameters -> make_proof store l2_parameters deposit >>= fun proof -> - Incremental.begin_construction b >>=? fun i -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -2391,7 +2441,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -2483,14 +2535,14 @@ module Rejection = struct Incremental.add_operation i op >>=? fun i -> Incremental.finalize_block i >>=? fun b -> (* Now we produce a valid proof rejecting the commitment *) - l2_parameters (I i) >>=? fun l2_parameters -> + l2_parameters (B b) >>=? fun l2_parameters -> make_proof store l2_parameters message >>= fun proof -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (B b) + reject_with_valid_prerejection + b account tx_rollup level @@ -2502,8 +2554,9 @@ module Rejection = struct ~proof ~previous_message_result:(message_result l2_context_hash []) ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> - Incremental.add_operation i op >>=? fun _ -> return_unit + ~commitment + >>=? fun (operation, b) -> + Block.bake b ~operation >>=? fun _ -> return_unit (** It is really similar to {!test_valid_proof_on_invalid_commitment} but it tries to reject a valid commitment, thus, fails. *) @@ -2543,8 +2596,8 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (B b) + reject_with_valid_prerejection + b account tx_rollup level @@ -2556,7 +2609,9 @@ module Rejection = struct ~proof ~previous_message_result:(message_result l2_context_hash []) ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -2584,7 +2639,6 @@ module Rejection = struct make_deposit b tx_rollup contract1 addr >>=? fun (b, (deposit_message, _), _ticket_hash) -> Context.Contract.balance (B b) contract1 >>=? fun balance -> - Context.Contract.balance (B b) contract2 >>=? fun balance2 -> (* [check_frozen] checks that contract1 has [expect] frozen tez. *) let check_frozen ~loc i expect = Contract.get_frozen_bonds (Incremental.alpha_ctxt i) contract1 @@ -2634,15 +2688,14 @@ module Rejection = struct >>=? fun () -> check_frozen ~loc:__LOC__ i bond_cost >>=? fun () -> Incremental.finalize_block i >>=? fun b -> - Incremental.begin_construction b >>=? fun i -> (* Now we produce a valid proof rejecting the second commitment *) make_proof store l2_parameters message >>= fun proof -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment1 ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b contract2 tx_rollup level1 @@ -2654,19 +2707,17 @@ module Rejection = struct ~proof ~previous_message_result:(message_result l2_context_hash []) ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> - Incremental.add_operation i op >>=? fun i -> + ~commitment:commitment1 + >>=? fun (operation, b) -> + Block.bake b ~operation >>=? fun b -> + Incremental.begin_construction b >>=? fun i -> check_bond (Incremental.alpha_ctxt i) tx_rollup contract1 0 >>=? fun () -> Assert.balance_was_debited ~loc:__LOC__ (I i) contract1 balance bond_cost >>=? fun () -> (* Now we need to check that the tez is really gone -- not just frozen *) check_frozen ~loc:__LOC__ i Tez.zero >>=? fun () -> - let reward = assert_ok Tez.(bond_cost /? 2L) in - Assert.balance_was_credited ~loc:__LOC__ (I i) contract2 balance2 reward - >>=? fun () -> - (* Now, we can still reject the root commitment, but we won't get a reward *) + (* Now, we can still reject the root commitment. *) Context.Contract.balance (I i) contract1 >>=? fun balance -> - Context.Contract.balance (I i) contract2 >>=? fun balance2 -> make_proof store l2_parameters deposit_message >>= fun proof -> let message_hash = Tx_rollup_message_hash.hash_uncarbonated deposit_message @@ -2676,8 +2727,8 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment0 ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b contract2 tx_rollup level0 @@ -2689,14 +2740,15 @@ module Rejection = struct ~proof ~previous_message_result:(message_result l2_context_hash []) ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> - Incremental.add_operation i op >>=? fun i -> + ~commitment:commitment0 + >>=? fun (operation, b) -> + Block.bake b ~operation >>=? fun b -> + Incremental.begin_construction b >>=? fun i -> check_bond (Incremental.alpha_ctxt i) tx_rollup contract1 0 >>=? fun () -> Assert.balance_was_debited ~loc:__LOC__ (I i) contract1 balance Tez.zero >>=? fun () -> (* Now we need to check that the tez still really gone -- not just frozen *) - check_frozen ~loc:__LOC__ i Tez.zero >>=? fun () -> - Assert.balance_was_credited ~loc:__LOC__ (I i) contract2 balance2 Tez.zero + check_frozen ~loc:__LOC__ i Tez.zero (** Test the proof production (used in this test file) and the proof verification handles a hard failure. [make_bad_message] makes a @@ -2728,8 +2780,8 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (B b) + reject_with_valid_prerejection + b account tx_rollup level @@ -2741,8 +2793,10 @@ module Rejection = struct ~proof ~previous_message_result:(message_result l2_context_hash []) ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> - Incremental.add_operation i op >>=? fun i -> + ~commitment + >>=? fun (operation, b) -> + Block.bake b ~operation >>=? fun b -> + Incremental.begin_construction b >>=? fun i -> check_bond (Incremental.alpha_ctxt i) tx_rollup account 0 >>=? fun () -> return_unit @@ -2806,8 +2860,9 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract tx_rollup level @@ -2819,8 +2874,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> - Incremental.add_operation i op >>=? fun _ -> return_unit + ~commitment + >>=? fun (operation, b) -> + Block.bake b ~operation >>=? fun _ -> return_unit (** Test that an empty proof is not able to reject a valid commitment. *) let test_invalid_proof_on_invalid_commitment () = @@ -2833,8 +2889,9 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract tx_rollup level @@ -2846,7 +2903,9 @@ module Rejection = struct ~proof:invalid_proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -2874,8 +2933,9 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract tx_rollup level @@ -2887,7 +2947,9 @@ module Rejection = struct ~message_result_path ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -2905,7 +2967,7 @@ module Rejection = struct })) >>=? fun _ -> return_unit - (** Test that rejection successfully fails when there's no commitment to + (** Test that prerejection successfully fails when there's no commitment to reject *) let test_no_commitment () = context_init1 () >>=? fun (b, contract) -> @@ -2921,8 +2983,10 @@ module Rejection = struct let message_path = single_message_path message_hash in l2_parameters (I i) >>=? fun l2_parameters -> valid_empty_proof l2_parameters >>= fun proof -> - Op.tx_rollup_reject - (I i) + make_incomplete_commitment_for_batch (I i) level tx_rollup [] + >>=? fun (commitment, _) -> + reject_with_valid_prerejection + b contract tx_rollup level @@ -2934,14 +2998,15 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op ~expect_failure: (check_proto_error - (Tx_rollup_errors.Cannot_reject_level - {provided = level; accepted_range = None})) + Tx_rollup_errors.Rejection_for_nonexistent_commitment) >>=? fun _ -> return_unit (** Test that rejection successfully fails when the rejected commitment is @@ -2971,8 +3036,9 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract tx_rollup level @@ -2984,7 +3050,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -3015,8 +3083,9 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract1 tx_rollup level @@ -3028,7 +3097,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -3041,14 +3112,15 @@ module Rejection = struct exist in the inbox. *) let test_wrong_message_position () = init_with_valid_commitment () - >>=? fun (i, contract1, tx_rollup, level, message, _commitment) -> + >>=? fun (i, contract1, tx_rollup, level, message, commitment) -> let (message, _size) = Tx_rollup_message.make_batch message in let message_hash = Tx_rollup_message_hash.hash_uncarbonated message in let message_path = single_message_path message_hash in l2_parameters (I i) >>=? fun l2_parameters -> valid_empty_proof l2_parameters >>= fun proof -> - Op.tx_rollup_reject - (I i) + Incremental.finalize_block i >>=? fun b -> + reject_with_valid_prerejection + b contract1 tx_rollup level @@ -3060,7 +3132,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -3086,13 +3160,12 @@ module Rejection = struct Op.tx_rollup_commit (I i) account tx_rollup commitment >>=? fun op -> Incremental.add_operation i op >>=? fun i -> Incremental.finalize_block i >>=? fun b -> - Incremental.begin_construction b >>=? fun i -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -3104,7 +3177,9 @@ module Rejection = struct ~proof:invalid_proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op @@ -3114,8 +3189,8 @@ module Rejection = struct (* Check with a reasonable proof *) l2_parameters (I i) >>=? fun l2_parameters -> make_proof store l2_parameters deposit >>= fun proof -> - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -3127,7 +3202,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op >>=? fun _ -> return_unit let add_store_to_ctxt ctxt store = @@ -3163,13 +3240,12 @@ module Rejection = struct proof required is above [size], so the rejection should succeed. *) l2_parameters (I i) >>=? fun l2_parameters -> make_proof store l2_parameters deposit >>= fun proof -> - Incremental.begin_construction b >>=? fun i -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -3181,17 +3257,19 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> return (i, op) + ~commitment (** Test that a commitment which require a too-large proof can be rejected even if the after hash is correct. *) let test_too_large_rejection () = (* With a limit, the commitment is rejected because the required proof is above the limit. *) - test_large_rejection 100 >>=? fun (i, op) -> + test_large_rejection 100 >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op >>=? fun _ -> (* With a high limit, the commitment can not be rejected as it is valid *) - test_large_rejection 10_000 >>=? fun (i, op) -> + test_large_rejection 10_000 >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i ~expect_failure: @@ -3238,13 +3316,12 @@ module Rejection = struct in (* We try to reject with the truncated proof which is already above the size limit. *) - Incremental.begin_construction b >>=? fun i -> let message_position = 0 in let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -3256,7 +3333,9 @@ module Rejection = struct ~proof:proof_truncated ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op >>=? fun _ -> return_unit (** Create a context where the batcher submitted and committed for a layer2 @@ -3346,8 +3425,8 @@ module Rejection = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in - Op.tx_rollup_reject - (B b) + reject_with_valid_prerejection + b account tx_rollup level @@ -3359,7 +3438,9 @@ module Rejection = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op ?expect_failure >>=? fun _ -> return_unit let test_reject_withdrawals_limit () = @@ -3534,8 +3615,8 @@ module Rejection = struct let truncated_node = drop_n proof_node 100 in {proof with state = (fun () -> truncated_node)} in - Op.tx_rollup_reject - (B b) + reject_with_valid_prerejection + b account tx_rollup Tx_rollup_level.root @@ -3547,12 +3628,54 @@ module Rejection = struct ~proof:proof_truncated ~previous_message_result:message0_result ~previous_message_result_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> Incremental.begin_construction b >>=? fun i -> (* Finally, we reject the commitment and check that the size fits in a Tezos operation. *) Incremental.add_operation ~check_size:true i op >>=? fun _i -> return_unit + (** [test_missing_prerejection] tests that rejection fails without a + corresponding prerejection *) + let test_missing_prerejection () = + init_l2_store () >>= fun store -> + init_with_valid_commitment () + >>=? fun (i, contract, tx_rollup, level, message, commitment) -> + l2_parameters (I i) >>=? fun l2_parameters -> + make_proof store l2_parameters (fst @@ Tx_rollup_message.make_batch message) + >>= fun proof -> + let (message, _size) = Tx_rollup_message.make_batch message in + let message_hash = Tx_rollup_message_hash.hash_uncarbonated message in + let message_path = + assert_ok Tx_rollup_inbox.Merkle.(compute_path [message_hash] 0) + in + let (message_result_hash, message_result_path) = + make_rejection_param commitment ~index:0 + in + Op.tx_rollup_reject + (I i) + contract + tx_rollup + level + message + ~message_position:0 + ~message_path + ~message_result_hash + ~message_result_path + ~proof + ~previous_message_result + ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path + ~commitment:Tx_rollup_commitment.(Compact.hash @@ Full.compact commitment) + >>=? fun op -> + Incremental.add_operation + i + op + ~expect_failure: + (check_proto_error Tx_rollup_errors.Rejection_without_prerejection) + >>=? fun i -> + ignore i ; + return_unit + let tests = [ Tztest.tztest @@ -3617,6 +3740,10 @@ module Rejection = struct "regression test rejection max proof size and message" `Quick test_rejection_size_limit; + Tztest.tztest + "reject with a missing prerejection" + `Quick + test_missing_prerejection; ] end @@ -3635,7 +3762,7 @@ module Single_message_inbox = struct Op.tx_rollup_submit_batch (B b) account tx_rollup contents >>=? fun operation -> Block.bake b ~operation - let reject ?expect_failure b tx_rollup account level commitment = + let reject ?expect_failure b tx_rollup account level commitment ~prereject = Format.printf "Rejecting level %a (%s)\n" Tx_rollup_level.pp @@ -3647,8 +3774,23 @@ module Single_message_inbox = struct let (message_result_hash, message_result_path) = message_result_hash_and_path commitment ~message_position in + Incremental.begin_construction b >>=? fun i -> + (if prereject then + Op.tx_rollup_prereject + (I i) + ~source:account + ~tx_rollup + ~level + ~message_position:0 + ~proof + >>=? fun op -> Incremental.add_operation i op + else return i) + >>=? fun i -> + let commitment = + Tx_rollup_commitment.(Compact.hash @@ Full.compact commitment) + in Op.tx_rollup_reject - (B b) + (I i) account tx_rollup level @@ -3660,8 +3802,8 @@ module Single_message_inbox = struct ~proof ~previous_message_result:Rejection.previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path + ~commitment >>=? fun operation -> - Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i operation ?expect_failure >>=? fun i -> Incremental.finalize_block i @@ -3733,7 +3875,8 @@ let test_state () = Commits: [A1] [A2] *) (* Reject the commitment *) - reject b tx_rollup account1 Tx_rollup_level.root commit1 >>=? fun b -> + reject b tx_rollup account1 Tx_rollup_level.root commit1 ~prereject:true + >>=? fun b -> (* Inboxes: [ ] - [ ] - [ ] Commits: @@ -3782,7 +3925,8 @@ let test_state () = Commits: [A2] [A1] *) (* Reject the first commitment *) - reject b tx_rollup account2 Tx_rollup_level.root commit1 >>=? fun b -> + reject b tx_rollup account2 Tx_rollup_level.root commit1 ~prereject:true + >>=? fun b -> (* Check that we went back to the initial state *) (* Inboxes: [ ] - [ ] - [ ] @@ -3815,7 +3959,7 @@ let test_state () = Block.bake b ~operations:[] >>=? fun b -> Op.tx_rollup_finalize (B b) account1 tx_rollup >>=? fun operation -> Block.bake b ~operation >>=? fun b -> - (* Check we cannot finalize root anymore *) + (* Check we cannot reject root anymore *) reject b tx_rollup @@ -3826,9 +3970,17 @@ let test_state () = (check_proto_error_f (function | Tx_rollup_errors.Cannot_reject_level _ -> true | _ -> false)) + ~prereject:false >>=? fun b -> (* We can reject level 1 *) - reject b tx_rollup account2 Tx_rollup_level.(succ root) commit2 >>=? fun b -> + reject + b + tx_rollup + account2 + Tx_rollup_level.(succ root) + commit2 + ~prereject:true + >>=? fun b -> (* There is no commitment to finalize anymore *) Block.bake b ~operations:[] >>=? fun b -> Block.bake b ~operations:[] >>=? fun b -> @@ -3904,7 +4056,8 @@ let test_state_with_deleted () = Op.tx_rollup_remove_commitment (B b) account1 tx_rollup >>=? fun operation -> Block.bake ~operation b >>=? fun b -> (* Reject level 1, it works *) - reject b tx_rollup account1 commit1.level commit1 >>=? fun b -> + reject b tx_rollup account1 commit1.level commit1 ~prereject:true + >>=? fun b -> ignore b ; return_unit @@ -5137,7 +5290,6 @@ module Withdraw = struct >>=? fun i -> Incremental.add_operation i operation >>=? fun i -> Incremental.finalize_block i >>=? fun b -> - Incremental.begin_construction b >>=? fun i -> let message_position = 0 in let message_path = single_message_path @@ Tx_rollup_message_hash.hash_uncarbonated message @@ -5145,8 +5297,8 @@ module Withdraw = struct let message_result_path = compute_message_result_path commitment ~message_position in - Op.tx_rollup_reject - (I i) + Rejection.reject_with_valid_prerejection + b account tx_rollup level @@ -5158,7 +5310,9 @@ module Withdraw = struct ~proof ~previous_message_result ~previous_message_result_path:Tx_rollup_commitment.Merkle.dummy_path - >>=? fun op -> + ~commitment + >>=? fun (op, b) -> + Incremental.begin_construction b >>=? fun i -> Incremental.add_operation i op diff --git a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml index 7276ef13939e..fbfad769ae14 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml @@ -410,3 +410,17 @@ let reject_commitment ctxt rollup state level = >>=? fun (ctxt, pred_hash) -> Tx_rollup_state_repr.record_commitment_rejection state level pred_hash >>?= fun state -> return (ctxt, state) + +let commitment_exists : + Raw_context.t -> + Tx_rollup_repr.t -> + Tx_rollup_state_repr.t -> + Tx_rollup_level_repr.t -> + Hash.t -> + (Raw_context.t * bool) tzresult Lwt.t = + fun ctxt tx_rollup state level commitment_to_check -> + find ctxt tx_rollup state level >>=? fun (ctxt, commitment) -> + match commitment with + | None -> return (ctxt, false) + | Some commitment -> + return (ctxt, Hash.(commitment.commitment_hash = commitment_to_check)) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli index d27364953397..3a8a69b96b36 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli @@ -195,3 +195,14 @@ val check_agreed_and_disputed_results : disputed_position:int -> disputed_result_path:Tx_rollup_commitment_repr.Merkle.path -> Raw_context.t tzresult Lwt.t + +(** [commitment_exists ctxt tx_rollup level commitment_hash] + checks that the commitment at level [level] is equal to + [commitment_hash]. *) +val commitment_exists : + Raw_context.t -> + Tx_rollup_repr.t -> + Tx_rollup_state_repr.t -> + Tx_rollup_level_repr.t -> + Tx_rollup_commitment_repr.Hash.t -> + (Raw_context.t * bool) tzresult Lwt.t diff --git a/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index cf7ba36b9ebf..c412dd7aef81 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -675,6 +675,10 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "title": "A Tezos protocol ID (Base58Check-encoded)", "$ref": "#/definitions/unistring" }, + "Rejection_hash": { + "title": "A rejection ID (Base58Check-encoded)", + "$ref": "#/definitions/unistring" + }, "Signature": { "title": "A Ed25519, Secp256k1 or P256 signature (Base58Check-encoded)", "$ref": "#/definitions/unistring" @@ -2508,9 +2512,13 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "version" ], "additionalProperties": false + }, + "commitment": { + "$ref": "#/definitions/Commitment_hash" } }, "required": [ + "commitment", "proof", "previous_message_result_path", "previous_message_result", @@ -2981,6 +2989,50 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Tx_rollup_prerejection", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "tx_rollup_prerejection" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "tx_rollup": { + "$ref": "#/definitions/alpha.tx_rollup_id" + }, + "hash": { + "$ref": "#/definitions/Rejection_hash" + } + }, + "required": [ + "hash", + "tx_rollup", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Sc_rollup_originate", "type": "object", @@ -5491,6 +5543,17 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "kind": "Dynamic" }, "kind": "named" + }, + { + "name": "commitment", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 32, + "kind": "Float" + }, + "kind": "named" } ], "name": "Tx_rollup_rejection" @@ -5807,6 +5870,102 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Transfer_ticket" }, + { + "tag": 159, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "source", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "fee", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "counter", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "gas_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "storage_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "tx_rollup", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 20, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "hash", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 20, + "kind": "Float" + }, + "kind": "named" + } + ], + "name": "Tx_rollup_prerejection" + }, { "tag": 200, "fields": [ @@ -10168,6 +10327,10 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "title": "A Tezos protocol ID (Base58Check-encoded)", "$ref": "#/definitions/unistring" }, + "Rejection_hash": { + "title": "A rejection ID (Base58Check-encoded)", + "$ref": "#/definitions/unistring" + }, "Signature": { "title": "A Ed25519, Secp256k1 or P256 signature (Base58Check-encoded)", "$ref": "#/definitions/unistring" @@ -12001,9 +12164,13 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "version" ], "additionalProperties": false + }, + "commitment": { + "$ref": "#/definitions/Commitment_hash" } }, "required": [ + "commitment", "proof", "previous_message_result_path", "previous_message_result", @@ -12474,6 +12641,50 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Tx_rollup_prerejection", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "tx_rollup_prerejection" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "tx_rollup": { + "$ref": "#/definitions/alpha.tx_rollup_id" + }, + "hash": { + "$ref": "#/definitions/Rejection_hash" + } + }, + "required": [ + "hash", + "tx_rollup", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Sc_rollup_originate", "type": "object", diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index 80ef49f6a42a..97405ebcf494 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -696,6 +696,10 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "title": "A Tezos protocol ID (Base58Check-encoded)", "$ref": "#/definitions/unistring" }, + "Rejection_hash": { + "title": "A rejection ID (Base58Check-encoded)", + "$ref": "#/definitions/unistring" + }, "Signature": { "title": "A Ed25519, Secp256k1 or P256 signature (Base58Check-encoded)", "$ref": "#/definitions/unistring" @@ -2529,9 +2533,13 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "version" ], "additionalProperties": false + }, + "commitment": { + "$ref": "#/definitions/Commitment_hash" } }, "required": [ + "commitment", "proof", "previous_message_result_path", "previous_message_result", @@ -3002,6 +3010,50 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Tx_rollup_prerejection", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "tx_rollup_prerejection" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "tx_rollup": { + "$ref": "#/definitions/alpha.tx_rollup_id" + }, + "hash": { + "$ref": "#/definitions/Rejection_hash" + } + }, + "required": [ + "hash", + "tx_rollup", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Sc_rollup_originate", "type": "object", @@ -5512,6 +5564,17 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "kind": "Dynamic" }, "kind": "named" + }, + { + "name": "commitment", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 32, + "kind": "Float" + }, + "kind": "named" } ], "name": "Tx_rollup_rejection" @@ -5828,6 +5891,102 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Transfer_ticket" }, + { + "tag": 159, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "source", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "fee", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "counter", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "gas_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "storage_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "tx_rollup", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 20, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "hash", + "layout": { + "kind": "Bytes" + }, + "data_kind": { + "size": 20, + "kind": "Float" + }, + "kind": "named" + } + ], + "name": "Tx_rollup_prerejection" + }, { "tag": 200, "fields": [ @@ -10189,6 +10348,10 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "title": "A Tezos protocol ID (Base58Check-encoded)", "$ref": "#/definitions/unistring" }, + "Rejection_hash": { + "title": "A rejection ID (Base58Check-encoded)", + "$ref": "#/definitions/unistring" + }, "Signature": { "title": "A Ed25519, Secp256k1 or P256 signature (Base58Check-encoded)", "$ref": "#/definitions/unistring" @@ -12022,9 +12185,13 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "version" ], "additionalProperties": false + }, + "commitment": { + "$ref": "#/definitions/Commitment_hash" } }, "required": [ + "commitment", "proof", "previous_message_result_path", "previous_message_result", @@ -12495,6 +12662,50 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Tx_rollup_prerejection", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "tx_rollup_prerejection" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "tx_rollup": { + "$ref": "#/definitions/alpha.tx_rollup_id" + }, + "hash": { + "$ref": "#/definitions/Rejection_hash" + } + }, + "required": [ + "hash", + "tx_rollup", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Sc_rollup_originate", "type": "object", -- GitLab From 5467a3934c1aa93a8a2614253708a5846adfbc35 Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 4 Mar 2022 10:45:58 -0500 Subject: [PATCH 3/6] Proto,Tx_rollup: Prerejection finalization --- .../lib_protocol/alpha_context.mli | 13 ++++- src/proto_alpha/lib_protocol/apply.ml | 2 +- .../integration/operations/test_tx_rollup.ml | 58 ++++++++++++++++++- .../tx_rollup_commitment_storage.ml | 7 ++- .../tx_rollup_commitment_storage.mli | 11 +++- .../tx_rollup_rejection_storage.ml | 38 ++++++++++++ .../tx_rollup_rejection_storage.mli | 6 ++ 7 files changed, 126 insertions(+), 9 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 3e19ee95dcdd..f599888eeed9 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2001,7 +2001,12 @@ module Tx_rollup_commitment : sig context -> Tx_rollup.t -> Tx_rollup_state.t -> - (context * Tx_rollup_state.t * Tx_rollup_level.t) tzresult Lwt.t + (context + * Tx_rollup_state.t + * Tx_rollup_level.t + * Signature.public_key_hash list) + tzresult + Lwt.t val remove_commitment : context -> @@ -2093,6 +2098,12 @@ module Tx_rollup_rejection : sig proof:Tx_rollup_l2_proof.t -> priority:int32 -> context tzresult Lwt.t + + val finalize_prerejections : + context -> + Tx_rollup.t -> + Tx_rollup_level.t -> + (context * Signature.public_key_hash list) tzresult Lwt.t end module Tx_rollup_errors : sig diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 7ce1ba5c31d0..199cc461c405 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1621,7 +1621,7 @@ let apply_external_manager_operation_content : | Tx_rollup_finalize_commitment {tx_rollup} -> Tx_rollup_state.get ctxt tx_rollup >>=? fun (ctxt, state) -> Tx_rollup_commitment.finalize_commitment ctxt tx_rollup state - >>=? fun (ctxt, state, level) -> + >>=? fun (ctxt, state, level, _to_reward) -> Tx_rollup_state.update ctxt tx_rollup state >>=? fun ctxt -> let result = Tx_rollup_finalize_commitment_result diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml index 4999a35c0790..d91c904dbebd 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_tx_rollup.ml @@ -3639,11 +3639,31 @@ module Rejection = struct corresponding prerejection *) let test_missing_prerejection () = init_l2_store () >>= fun store -> - init_with_valid_commitment () - >>=? fun (i, contract, tx_rollup, level, message, commitment) -> + context_init2 () >>=? fun (b, (contract1, contract2)) -> + originate b contract1 >>=? fun (b, tx_rollup) -> + let message = "bogus" in + Op.tx_rollup_submit_batch (B b) contract1 tx_rollup message + >>=? fun operation -> + Block.bake ~operation b >>=? fun b -> + Incremental.begin_construction b >>=? fun i -> + let level = Tx_rollup_level.root in + make_incomplete_commitment_for_batch (I i) level tx_rollup [] + >>=? fun (commitment, _ctxt) -> + Op.tx_rollup_commit (I i) contract1 tx_rollup commitment >>=? fun op -> + Incremental.add_operation i op >>=? fun i -> l2_parameters (I i) >>=? fun l2_parameters -> make_proof store l2_parameters (fst @@ Tx_rollup_message.make_batch message) >>= fun proof -> + (* We create a prerejection for contract1... *) + Op.tx_rollup_prereject + (I i) + ~source:contract1 + ~tx_rollup + ~level + ~message_position:0 + ~proof + >>=? fun op -> + Incremental.add_operation i op >>=? fun i -> let (message, _size) = Tx_rollup_message.make_batch message in let message_hash = Tx_rollup_message_hash.hash_uncarbonated message in let message_path = @@ -3652,9 +3672,10 @@ module Rejection = struct let (message_result_hash, message_result_path) = make_rejection_param commitment ~index:0 in + (*... but contract2 tries to reject *) Op.tx_rollup_reject (I i) - contract + contract2 tx_rollup level message @@ -3676,6 +3697,33 @@ module Rejection = struct ignore i ; return_unit + (** [test_prerejection_without_inbox] tests that rejection fails + when there are no inboxes at all. Mainly for coverage. *) + let test_prerejection_without_inbox () = + context_init1 () >>=? fun (b, contract) -> + originate b contract >>=? fun (b, tx_rollup) -> + Incremental.begin_construction b >>=? fun i -> + let level = Tx_rollup_level.root in + l2_parameters (I i) >>=? fun l2_parameters -> + valid_empty_proof l2_parameters >>= fun proof -> + Op.tx_rollup_prereject + (I i) + ~source:contract + ~tx_rollup + ~level + ~message_position:0 + ~proof + >>=? fun op -> + Incremental.add_operation + i + op + ~expect_failure: + (check_proto_error Tx_rollup_errors.Prerejection_without_inbox) + >>=? fun i -> + ignore i ; + + return () + let tests = [ Tztest.tztest @@ -3744,6 +3792,10 @@ module Rejection = struct "reject with a missing prerejection" `Quick test_missing_prerejection; + Tztest.tztest + "Test missing inbox for prerejection" + `Quick + test_prerejection_without_inbox; ] end diff --git a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml index fbfad769ae14..bdd0548cacac 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.ml @@ -296,9 +296,14 @@ let finalize_commitment ctxt rollup state = >>=? fun (ctxt, _commitment_size_alloc) -> (* See {{Note}} for a rationale on why ignoring storage allocation is safe. *) + Tx_rollup_rejection_storage.finalize_prerejections + ctxt + rollup + oldest_inbox_level + >>=? fun (ctxt, to_reward) -> (* We update the state *) Tx_rollup_state_repr.record_inbox_deletion state oldest_inbox_level - >>?= fun state -> return (ctxt, state, oldest_inbox_level) + >>?= fun state -> return (ctxt, state, oldest_inbox_level, to_reward) | None -> fail No_commitment_to_finalize let remove_commitment ctxt rollup state = diff --git a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli index 3a8a69b96b36..161a813df455 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_commitment_storage.mli @@ -151,13 +151,18 @@ val has_bond : The state of the rollup is adjusted accordingly, and the finalized level is returned. Besides, the inbox at said level is removed - from the context. This function returns the new context, and the - new state. *) + from the context. This function returns: the new context, the + new state, the level finalized, and a list of contracts to reward + for rejections. *) val finalize_commitment : Raw_context.t -> Tx_rollup_repr.t -> Tx_rollup_state_repr.t -> - (Raw_context.t * Tx_rollup_state_repr.t * Tx_rollup_level_repr.t) tzresult + (Raw_context.t + * Tx_rollup_state_repr.t + * Tx_rollup_level_repr.t + * Signature.public_key_hash list) + tzresult Lwt.t (** [remove_commitment ctxt tx_rollup state] tries to remove the diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml index 3348dc14be44..1eff935db3b6 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.ml @@ -126,3 +126,41 @@ let update_accepted_prerejection : commitment new_prerejection >>=? fun (ctxt, _, _) -> return ctxt + +let finalize_prerejections ctxt tx_rollup level = + (* Find all of the accepted prerejections for this level *) + Storage.Tx_rollup.Accepted_prerejections.list_values ((ctxt, tx_rollup), level) + >>=? fun (ctxt, accepted_prerejections) -> + let to_reward = + List.map + (fun (accepted : Tx_rollup_rejection_repr.prerejection) -> + accepted.contract) + accepted_prerejections + in + (* Remove them *) + List.fold_left_es + (fun ctxt (accepted : Tx_rollup_rejection_repr.prerejection) -> + Storage.Tx_rollup.Accepted_prerejections.remove + ((ctxt, tx_rollup), level) + accepted.hash + >|=? fun (ctxt, _, _) -> ctxt) + ctxt + accepted_prerejections + >>=? fun ctxt -> + (* Now, find all of the prerejections submitted for this level *) + Storage.Tx_rollup.Prerejections_by_index.list_values ((ctxt, tx_rollup), level) + >>=? fun (ctxt, prerejections) -> + List.fold_left_es + (fun ctxt prerejection -> + Storage.Tx_rollup.Prerejection.get ctxt prerejection + >>=? fun (ctxt, (_, index)) -> + (* Remove the prerejection from both tables *) + Storage.Tx_rollup.Prerejection.remove ctxt prerejection + >>=? fun (ctxt, _, _) -> + Storage.Tx_rollup.Prerejections_by_index.remove + ((ctxt, tx_rollup), level) + index + >|=? fun (ctxt, _, _) -> ctxt) + ctxt + prerejections + >|=? fun ctxt -> (ctxt, to_reward) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli index 068b9481cda9..de84a6f014f2 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_rejection_storage.mli @@ -51,3 +51,9 @@ val update_accepted_prerejection : proof:Tx_rollup_l2_proof.t -> priority:int32 -> Raw_context.t tzresult Lwt.t + +val finalize_prerejections : + Raw_context.t -> + Tx_rollup_repr.t -> + Tx_rollup_level_repr.t -> + (Raw_context.t * Signature.public_key_hash list) tzresult Lwt.t -- GitLab From 7f88b2ceafd79c5f061d5ecc6405729989a8b51c Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 16 Mar 2022 16:23:47 -0400 Subject: [PATCH 4/6] Proto,tx_rollup: Reward successful prerejections --- src/proto_alpha/lib_protocol/apply.ml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 199cc461c405..b57647256421 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1621,13 +1621,27 @@ let apply_external_manager_operation_content : | Tx_rollup_finalize_commitment {tx_rollup} -> Tx_rollup_state.get ctxt tx_rollup >>=? fun (ctxt, state) -> Tx_rollup_commitment.finalize_commitment ctxt tx_rollup state - >>=? fun (ctxt, state, level, _to_reward) -> + >>=? fun (ctxt, state, level, to_reward) -> + let burn = Constants.tx_rollup_commitment_bond ctxt in + Tez.(burn /? 2L) >>?= fun reward -> + List.fold_left_es + (fun (ctxt, acc) accuser -> + let accuser = Contract.implicit_contract accuser in + Token.transfer + ctxt + `Tx_rollup_rejection_rewards + (`Contract accuser) + reward + >>=? fun (ctxt, updates) -> return (ctxt, List.append acc updates)) + (ctxt, []) + to_reward + >>=? fun (ctxt, balance_updates) -> Tx_rollup_state.update ctxt tx_rollup state >>=? fun ctxt -> let result = Tx_rollup_finalize_commitment_result { consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; - balance_updates = []; + balance_updates; level; } in -- GitLab From b9d54e0f75d4fb237efed40ec647fd684625813d Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 25 Mar 2022 16:37:37 -0400 Subject: [PATCH 5/6] Proto,Tx_rollup: pp for proofs --- src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml | 4 ++++ src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml index f46f2e0dcda8..2d98a5b760ba 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.ml @@ -32,3 +32,7 @@ let ( = ) t1 t2 = let t1_bytes = Data_encoding.Binary.to_bytes_exn encoding t1 in let t2_bytes = Data_encoding.Binary.to_bytes_exn encoding t2 in Compare.Bytes.(t1_bytes = t2_bytes) + +let pp fmt t = + let json = Data_encoding.Json.construct encoding t in + Data_encoding.Json.pp fmt json diff --git a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli index 5a241063d0a2..85bf794cbaae 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_l2_proof.mli @@ -30,3 +30,5 @@ type t = Context.Proof.stream Context.Proof.t val encoding : t Data_encoding.t val ( = ) : t -> t -> bool + +val pp : Format.formatter -> t -> unit -- GitLab From a1d60a93c8fe6b3c19e34918de676a2de1c6faea Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 25 Mar 2022 16:37:08 -0400 Subject: [PATCH 6/6] Tx_rollup: make tezt tests send prerejections --- .../main_tx_rollup_node_alpha.ml | 80 +++++++++++- .../lib_client/client_proto_context.ml | 39 ++++++ .../lib_client/client_proto_context.mli | 25 ++++ .../client_proto_context_commands.ml | 81 ++++++++++++ src/proto_alpha/lib_tx_rollup/l1_operation.ml | 2 + tezt/_regressions/tx_rollup_rejection.out | 58 +++++++-- tezt/lib_tezos/client.ml | 27 +++- tezt/lib_tezos/client.mli | 20 ++- tezt/lib_tezos/operation.ml | 15 ++- tezt/lib_tezos/operation.mli | 2 + tezt/tests/tx_rollup.ml | 118 +++++++++++++++++- tezt/tests/tx_rollup_node.ml | 82 ++++++++++++ 12 files changed, 524 insertions(+), 25 deletions(-) diff --git a/src/proto_alpha/bin_tx_rollup_node/main_tx_rollup_node_alpha.ml b/src/proto_alpha/bin_tx_rollup_node/main_tx_rollup_node_alpha.ml index bf738b76db1e..630248898098 100644 --- a/src/proto_alpha/bin_tx_rollup_node/main_tx_rollup_node_alpha.ml +++ b/src/proto_alpha/bin_tx_rollup_node/main_tx_rollup_node_alpha.ml @@ -80,6 +80,14 @@ let rejection_signer_arg = ~doc:"The signer for rejections" () +let source_arg = + let doc = "The public key which will submit the rejection" in + Clic.arg + ~long:"source" + ~placeholder:"public_key" + ~doc + (Clic.parameter (fun _ -> Client_keys.Public_key_hash.of_source)) + let rollup_id_arg = Clic.arg ~long:"rollup-id" @@ -90,6 +98,43 @@ let rollup_id_arg = | Ok x -> return x | Error _ -> failwith "Invalid Rollup Id")) +let level_arg = + Clic.arg + ~long:"level" + ~placeholder:"level" + ~doc:"The rollup level to target" + (Clic.parameter (fun _ s -> + match Int32.of_string_opt s with + | Some x -> ( + match Protocol.Alpha_context.Tx_rollup_level.of_int32 x with + | Ok x -> return x + | Error _ -> failwith "Invalid level") + | None -> failwith "Invalid level")) + +let message_position_arg = + Clic.arg + ~long:"message-position" + ~placeholder:"message position" + ~doc:"The message position to target" + (Clic.parameter (fun _ s -> + match Int32.of_string_opt s with + | Some x -> return @@ Int32.to_int x + | None -> failwith "Invalid message position")) + +let proof_arg = + Clic.arg + ~long:"proof" + ~placeholder:"proof (json)" + ~doc:"The proof" + (Clic.parameter (fun _ s -> + match Data_encoding.Json.from_string s with + | Ok json -> + return + @@ Data_encoding.Json.destruct + Protocol.Tx_rollup_l2_proof.encoding + json + | Error e -> failwith "%s" e)) + let rollup_genesis_arg = Clic.arg ~long:"rollup-genesis" @@ -196,6 +241,39 @@ let configuration_init_command = let*! () = Event.(emit configuration_was_written) (file, config) in return_unit) +let hash_rejection_command = + let open Clic in + command + ~group + ~desc:"Generate a rejection hash for a prerejection." + (args5 source_arg rollup_id_arg level_arg message_position_arg proof_arg) + (prefixes ["hash"; "rejection"] @@ stop) + (fun (source, tx_rollup, level, message_position, proof) cctxt -> + let open Lwt_result_syntax in + let*! () = Event.(emit preamble_warning) () in + let* source = to_tzresult "Missing arg --source" source in + let* tx_rollup = to_tzresult "Missing arg --rollup_id" tx_rollup in + let* level = to_tzresult "Missing arg --level" level in + let* message_position = + to_tzresult "Missing arg --message-position" message_position + in + let* proof = to_tzresult "Missing arg --proof" proof in + + let hash = + Protocol.Alpha_context.Tx_rollup_rejection.generate_prerejection + ~source + ~tx_rollup + ~level + ~message_position + ~proof + in + let hash_str = + Protocol.Alpha_context.Tx_rollup_rejection.Rejection_hash.to_b58check + hash + in + let*! () = cctxt#message "%s" hash_str in + return_unit) + let run_command = let open Lwt_result_syntax in let open Clic in @@ -221,7 +299,7 @@ let run_command = let tx_rollup_commands () = List.map (Clic.map_command (new Protocol_client_context.wrap_full)) - [configuration_init_command; run_command] + [configuration_init_command; run_command; hash_rejection_command] let select_commands _ _ = return (tx_rollup_commands ()) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index 9dd19b6c1e59..e369508cbd00 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -1099,6 +1099,45 @@ let tx_rollup_dispatch_tickets (cctxt : #full) ~chain ~block ?confirmations | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return (oph, op, result) +let submit_tx_rollup_prerejection (cctxt : #full) ~chain ~block ?confirmations + ?dry_run ?verbose_signing ?simulation ?fee ?gas_limit ?storage_limit + ?counter ~source ~src_pk ~src_sk ~fee_parameter ~tx_rollup ~hash () = + (match Tx_rollup_rejection.Rejection_hash.of_b58check_opt hash with + | Some hash -> return hash + | None -> failwith "%s is not a valid notation for a rejection hash" hash) + >>=? fun hash -> + let contents : + Kind.tx_rollup_prerejection Annotated_manager_operation.annotated_list = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Tx_rollup_prerejection {tx_rollup; hash})) + in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~successor_level:true + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ~src_pk + ~src_sk + ~fee_parameter + contents + >>=? fun (oph, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + let transfer_ticket (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?verbose_signing ?simulation ?fee ?gas_limit ?storage_limit ?counter ~source ~src_pk ~src_sk ~fee_parameter ~contents ~ty ~ticketer ~amount ~destination diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index bc35f7d7c63c..814507d4e86c 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -663,6 +663,31 @@ val transfer_ticket : tzresult Lwt.t +val submit_tx_rollup_prerejection : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.tez -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + source:Signature.public_key_hash -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + tx_rollup:Tx_rollup.t -> + hash:string -> + unit -> + (Operation_hash.t + * Kind.tx_rollup_prerejection Kind.manager contents + * Kind.tx_rollup_prerejection Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + val sc_rollup_originate : #Protocol_client_context.full -> chain:Chain_services.chain -> diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index ba2e53a61350..d960ac2fd1f7 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -2967,6 +2967,87 @@ let commands_rw () = ~entrypoint () >>=? fun _res -> return_unit); + command + ~group + ~desc:"Submit an optimistic transaction rollup prerejection operation." + (args12 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + storage_limit_arg + counter_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + (prefixes ["submit"; "tx"; "rollup"; "prerejection"] + @@ prefix "with" @@ prefix "hash" + @@ Clic.param + ~name:"hash" + ~desc:"the prerejection hash" + Client_proto_args.string_parameter + @@ prefix "to" + @@ Tx_rollup.tx_rollup_address_param + ~usage:"Tx rollup receiving the prerejection." + @@ prefix "from" + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the account rejecting the commitment." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + storage_limit, + counter, + force_low_fee, + fee_cap, + burn_cap ) + hash + tx_rollup + (_, source) + cctxt -> + match Contract.is_implicit source with + | None -> + failwith + "Only implicit accounts can reject transaction rollup commitments" + | Some source -> + Client_keys.get_key cctxt source >>=? fun (_, src_pk, src_sk) -> + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + submit_tx_rollup_prerejection + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?dry_run:(Some dry_run) + ?verbose_signing:(Some verbose_signing) + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~tx_rollup + ~hash + () + >>=? fun _res -> return_unit); command ~group ~desc:"Originate a new smart-contract rollup." diff --git a/src/proto_alpha/lib_tx_rollup/l1_operation.ml b/src/proto_alpha/lib_tx_rollup/l1_operation.ml index 178bafdd1c26..3b3ed7bb80a6 100644 --- a/src/proto_alpha/lib_tx_rollup/l1_operation.ml +++ b/src/proto_alpha/lib_tx_rollup/l1_operation.ml @@ -57,6 +57,7 @@ module Manager_operation = struct make tx_rollup_finalize_commitment_case; make tx_rollup_remove_commitment_case; make tx_rollup_rejection_case; + make tx_rollup_prerejection_case; make tx_rollup_dispatch_tickets_case; make transfer_ticket_case; make sc_rollup_originate_case; @@ -85,6 +86,7 @@ module Manager_operation = struct | Tx_rollup_remove_commitment _ -> tx_rollup_remove_commitment_case | Tx_rollup_rejection _ -> tx_rollup_rejection_case | Tx_rollup_dispatch_tickets _ -> tx_rollup_dispatch_tickets_case + | Tx_rollup_prerejection _ -> tx_rollup_prerejection_case | Transfer_ticket _ -> transfer_ticket_case | Sc_rollup_originate _ -> sc_rollup_originate_case | Sc_rollup_add_messages _ -> sc_rollup_add_messages_case diff --git a/tezt/_regressions/tx_rollup_rejection.out b/tezt/_regressions/tx_rollup_rejection.out index e13fbe39c653..a331fd421827 100644 --- a/tezt/_regressions/tx_rollup_rejection.out +++ b/tezt/_regressions/tx_rollup_rejection.out @@ -85,6 +85,46 @@ This sequence of operations was run: Consumed gas: 3694.292 +./tezos-client rpc get '/chains/main/blocks/head/context/tx_rollup/[TX_ROLLUP_HASH]/commitment/0' +{ "commitment": + { "level": 0, + "messages": + { "count": 1, + "root": "[TX_ROLLUP_MESSAGE_RESULT_LIST_HASH]", + "last_message_result_hash": + "[TX_ROLLUP_MESSAGE_RESULT_HASH]" }, + "predecessor": null, + "inbox_merkle_root": + "[TX_ROLLUP_INBOX_HASH]" }, + "commitment_hash": "[TX_ROLLUP_COMMITMENT_HASH]", + "committer": "[PUBLIC_KEY_HASH]", "submitted_at": 5 } + +./tezos-client --wait none submit tx rollup prerejection with hash rej1MWpY36dtim3iTmGLKWDVs1RC7aWhdX59C to '[TX_ROLLUP_HASH]' from '[PUBLIC_KEY_HASH]' +Node is bootstrapped. +Estimated gas: 2514.334 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000526 + Expected counter: 4 + Gas limit: 2615 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000526 + payload fees(the block proposer) ....... +ꜩ0.000526 + Tx rollup rejection:tx_rollup [TX_ROLLUP_HASH] hash rej1MWpY36dtim3iTmGLKWDVs1RC7aWhdX59C + From: [PUBLIC_KEY_HASH] + This tx rollup prerejection operation was successfully applied + Consumed gas: 2514.334 + + ./tezos-client --wait none reject commitment of tx rollup '[TX_ROLLUP_HASH]' at level 0 with result hash '[TX_ROLLUP_MESSAGE_RESULT_HASH]' and result path '[ "[TX_ROLLUP_MESSAGE_RESULT_LIST_HASH]" ]' for message at position 0 with content '{ "batch": "6262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262"}' and path '[ @@ -92,9 +132,9 @@ This sequence of operations was run: ]' with agreed context hash CoVu7Pqp1Gh3z33mink5T5Q2kAQKtnn3GHxVhyehdKZpQMBxFBGF and withdraw list hash txw1sFoLju3ySMAdY6v1dcHUMqJ4Zxc1kcynC8xkYgCmH6bpNSDhV and result path '[]' using proof '{ "version": 3, "before": { "node": "CoVu7Pqp1Gh3z33mink5T5Q2kAQKtnn3GHxVhyehdKZpQMBxFBGF" }, "after": { "node": "CoVu7Pqp1Gh3z33mink5T5Q2kAQKtnn3GHxVhyehdKZpQMBxFBGF" } , - "state": [] }' from '[PUBLIC_KEY_HASH]' + "state": [] }' with commitment '[TX_ROLLUP_COMMITMENT_HASH]' from '[PUBLIC_KEY_HASH]' Node is bootstrapped. -Estimated gas: 38301.662 units (will add 100 for safety) +Estimated gas: 39237.222 units (will add 100 for safety) Estimated storage: no bytes added Operation successfully injected in the node. Operation hash is '[OPERATION_HASH]' @@ -105,20 +145,18 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.009339 - Expected counter: 4 - Gas limit: 38402 + Fee to the baker: ꜩ0.009464 + Expected counter: 5 + Gas limit: 39338 Storage limit: 0 bytes Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.009339 - payload fees(the block proposer) ....... +ꜩ0.009339 + [PUBLIC_KEY_HASH] ... -ꜩ0.009464 + payload fees(the block proposer) ....... +ꜩ0.009464 Tx rollup rejection:[TX_ROLLUP_HASH] From: [PUBLIC_KEY_HASH] This tx rollup rejection operation was successfully applied Balance updates: Frozen_bonds([PUBLIC_KEY_HASH],[TX_ROLLUP_HASH]) ... -ꜩ10000 tx rollup rejection punishments ............................................................ +ꜩ10000 - tx rollup rejection rewards ................................................................ -ꜩ5000 - [PUBLIC_KEY_HASH] ....................................................... +ꜩ5000 - Consumed gas: 38301.662 + Consumed gas: 39237.222 diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 22e02dba88ef..cc0ddb5a5cf5 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -1370,7 +1370,7 @@ module Tx_rollup = struct let submit_rejection ?(wait = "none") ?burn_cap ?storage_limit ?hooks ~level ~message ~position ~path ~message_result_hash ~rejected_message_result_path ~agreed_message_result_path ~proof - ~context_hash ~withdraw_list_hash ~rollup ~src client = + ~context_hash ~withdraw_list_hash ~rollup ~src ~commitment client = let process = spawn_command ?hooks @@ -1386,7 +1386,9 @@ module Tx_rollup = struct @ ["with"; "agreed"; "context"; "hash"; context_hash] @ ["and"; "withdraw"; "list"; "hash"; withdraw_list_hash] @ ["and"; "result"; "path"; agreed_message_result_path] - @ ["using"; "proof"; proof; "from"; src] + @ ["using"; "proof"; proof] + @ ["with"; "commitment"; commitment] + @ ["from"; src] @ optional_arg ~name:"burn-cap" Tez.to_string burn_cap @ optional_arg ~name:"storage-limit" string_of_int storage_limit) in @@ -1490,6 +1492,27 @@ module Tx_rollup = struct in let parse process = Process.check process in {value = process; run = parse} + + let submit_prerejection ?(wait = "none") ?burn_cap ?storage_limit ?hooks ~hash + ~rollup ~src client = + let process = + spawn_command + ?hooks + client + (["--wait"; wait] + @ ["submit"; "tx"; "rollup"; "prerejection"] + @ ["with"; "hash"; hash] @ ["to"; rollup] @ ["from"; src] + @ Option.fold + ~none:[] + ~some:(fun burn_cap -> ["--burn-cap"; Tez.to_string burn_cap]) + burn_cap + @ Option.fold + ~none:[] + ~some:(fun s -> ["--storage-limit"; string_of_int s]) + storage_limit) + in + let parse process = Process.check process in + {value = process; run = parse} end let spawn_show_voting_period ?endpoint client = diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index e782da7ec1ab..8ac32fee71c8 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -1062,10 +1062,10 @@ module Tx_rollup : sig t -> unit Runnable.process - (** Run [tezos-client submit tx rollup rejection commitment at level + (** Run [tezos-client submit tx rollup reject commitment at level message at with with agreed - context hash and withdraw list - to from ]. *) + context hash and withdraw list + with commitment to from ]. *) val submit_rejection : ?wait:string -> ?burn_cap:Tez.t -> @@ -1083,6 +1083,20 @@ module Tx_rollup : sig withdraw_list_hash:string -> rollup:string -> src:string -> + commitment:string -> + t -> + unit Runnable.process + + (** Run [tezos-client submit tx rollup prerejection with hash + to from ]. *) + val submit_prerejection : + ?wait:string -> + ?burn_cap:Tez.t -> + ?storage_limit:int -> + ?hooks:Process.hooks -> + hash:string -> + rollup:string -> + src:string -> t -> unit Runnable.process diff --git a/tezt/lib_tezos/operation.ml b/tezt/lib_tezos/operation.ml index 7070ade32031..ea5ca9538cec 100644 --- a/tezt/lib_tezos/operation.ml +++ b/tezt/lib_tezos/operation.ml @@ -57,6 +57,7 @@ type manager_op_kind = previous_message_result_path : JSON.u; previous_message_context_hash : string; previous_message_withdraw_list_hash : string; + commitment : string; } | Delegation of (* public key hash *) string | Transfer_ticket of { @@ -153,7 +154,7 @@ let mk_rejection ~source ?counter ?(fee = 1_000_000) ?(gas_limit = 1_000_000) ?(storage_limit = 0) ~tx_rollup ~proof ~level ~message ~message_position ~message_path ~message_result_hash ~message_result_path ~previous_message_result_path ~previous_message_context_hash - ~previous_message_withdraw_list_hash client = + ~previous_message_withdraw_list_hash ~commitment client = mk_manager_op ~source ?counter ~fee ~gas_limit ~storage_limit client @@ Rejection { @@ -168,6 +169,7 @@ let mk_rejection ~source ?counter ?(fee = 1_000_000) ?(gas_limit = 1_000_000) previous_message_result_path; previous_message_context_hash; previous_message_withdraw_list_hash; + commitment; } let mk_transfer_ticket ~source ?counter ?(fee = 1_000_000) @@ -192,7 +194,8 @@ let manager_op_content_to_json_string ?(previous_message_result = `Null) ?(message_result_hash = `Null) ?(message_result_path = `Null) ?(previous_message_result_path = `Null) ?(ticket_contents = `Null) ?(ticket_ty = `Null) ?(ticket_ticketer = `Null) - ?(ticket_amount = `Null) ?(entrypoint = `Null) kind = + ?(ticket_amount = `Null) ?(entrypoint = `Null) ?(commitment = `Null) kind + = let filter = List.filter (fun (_k, v) -> v <> `Null) in return @@ `O @@ -223,6 +226,7 @@ let manager_op_content_to_json_string ("message_position", message_position); ("message_path", message_path); ("previous_message_result", previous_message_result); + ("commitment", commitment); ("level", level); ("message_result_hash", message_result_hash); ("message_result_path", message_result_path); @@ -272,6 +276,7 @@ let manager_op_content_to_json_string message_result_path; previous_message_result_path; previous_message_withdraw_list_hash; + commitment; } -> let rollup = `String tx_rollup in let proof = Ezjsonm.value_from_string proof in @@ -287,6 +292,7 @@ let manager_op_content_to_json_string ] in let message_result_hash = `String message_result_hash in + let commitment = `String commitment in mk_jsonm ~rollup ~proof @@ -298,6 +304,7 @@ let manager_op_content_to_json_string ~message_result_hash ~message_result_path ~previous_message_result_path + ~commitment "tx_rollup_rejection" | Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} -> let* ticket_contents = data_to_json client contents in @@ -487,7 +494,8 @@ let inject_rejection ?protocol ?async ?force ?wait_for_injection ?branch ~source ?(signer = source) ?counter ?fee ?gas_limit ?storage_limit ~tx_rollup ~proof ~level ~message ~message_position ~message_path ~message_result_hash ~message_result_path ~previous_message_result_path - ~previous_message_context_hash ~previous_message_withdraw_list_hash client = + ~previous_message_context_hash ~previous_message_withdraw_list_hash + ~commitment client = let* op = mk_rejection ~source @@ -506,6 +514,7 @@ let inject_rejection ?protocol ?async ?force ?wait_for_injection ?branch ~source ~previous_message_result_path ~previous_message_context_hash ~previous_message_withdraw_list_hash + ~commitment client in forge_and_inject_operation diff --git a/tezt/lib_tezos/operation.mli b/tezt/lib_tezos/operation.mli index 84a1c20ed673..c5ccaa501885 100644 --- a/tezt/lib_tezos/operation.mli +++ b/tezt/lib_tezos/operation.mli @@ -131,6 +131,7 @@ val mk_rejection : previous_message_result_path:JSON.u -> previous_message_context_hash:string -> previous_message_withdraw_list_hash:string -> + commitment:string -> Client.t -> manager_operation_content Lwt.t @@ -447,6 +448,7 @@ val inject_rejection : previous_message_result_path:JSON.u -> previous_message_context_hash:string -> previous_message_withdraw_list_hash:string -> + commitment:string -> Client.t -> [`OpHash of string] Lwt.t diff --git a/tezt/tests/tx_rollup.ml b/tezt/tests/tx_rollup.ml index 7ab56451c91e..cba5780bb871 100644 --- a/tezt/tests/tx_rollup.ml +++ b/tezt/tests/tx_rollup.ml @@ -134,7 +134,7 @@ let submit_remove_commitment ?(src = Constant.bootstrap1.public_key_hash) let submit_rejection ?(src = Constant.bootstrap1.public_key_hash) ~level ~message ~position ~proof {rollup; client; node = _} ~context_hash - ~withdraw_list_hash = + ~withdraw_list_hash ~commitment = Client.Tx_rollup.submit_rejection ~hooks ~level @@ -145,6 +145,7 @@ let submit_rejection ?(src = Constant.bootstrap1.public_key_hash) ~level ~src ~context_hash ~withdraw_list_hash + ~commitment client let bake_and_wait ?(nb = 1) client node = @@ -154,6 +155,32 @@ let bake_and_wait ?(nb = 1) client node = let* _n = Node.wait_for_level node (current_level + 1) in unit) +let submit_prerejection ?(src = Constant.bootstrap1.public_key_hash) + {rollup; client; node = _} ~hash = + Client.Tx_rollup.submit_prerejection ~hooks ~hash ~rollup ~src client + +let generate_prerejection ~rollup ~level ~message_position ~proof = + let process = + Process.spawn + "./tezos-tx-rollup-node-alpha" + [ + "hash"; + "rejection"; + "--rollup-id"; + rollup; + "--source"; + Constant.bootstrap1.public_key_hash; + "--level"; + Int.to_string level; + "--message-position"; + Int.to_string message_position; + "--proof"; + proof; + ] + in + let* out = Process.check_and_read_stdout process in + return @@ String.trim out + (* This module only registers regressions tests. Those regressions tests should be used to ensure there is no regressions with the various RPCs exported by the tx_rollups. *) @@ -1065,6 +1092,19 @@ let test_rollup_last_commitment_is_rejected = client in let agreed_message_result_path = "[]" in + let*! commitment = + Rollup.get_commitment ~hooks ~block:"head" ~level:0 ~rollup client + in + let commitment = assert_some commitment in + let* prerejection = + generate_prerejection + ~rollup + ~level:0 + ~message_position:0 + ~proof:Constant.tx_rollup_proof_initial_state + in + let*! () = submit_prerejection ~hash:prerejection state in + let* () = Client.bake_for client in let*! () = submit_rejection ~level:0 @@ -1077,6 +1117,7 @@ let test_rollup_last_commitment_is_rejected = ~proof:Constant.tx_rollup_proof_initial_state ~context_hash:Constant.tx_rollup_empty_l2_context ~withdraw_list_hash:Constant.tx_rollup_empty_withdraw_list_hash + ~commitment:commitment.commitment_hash state in let* () = Client.bake_for client in @@ -1155,6 +1196,19 @@ let test_rollup_reject_position_one = ~position:1 client in + let*! commitment = + Rollup.get_commitment ~hooks ~block:"head" ~level:0 ~rollup client + in + let commitment = assert_some commitment in + let* prerejection = + generate_prerejection + ~rollup + ~level:0 + ~message_position:1 + ~proof:Constant.tx_rollup_proof_initial_state + in + let*! () = submit_prerejection ~hash:prerejection state in + let* () = Client.bake_for client in let*! () = submit_rejection ~level:0 @@ -1168,6 +1222,7 @@ let test_rollup_reject_position_one = ~proof:Constant.tx_rollup_proof_initial_state ~context_hash:Constant.tx_rollup_empty_l2_context ~withdraw_list_hash:Constant.tx_rollup_empty_withdraw_list_hash + ~commitment:commitment.commitment_hash state in let* () = Client.bake_for client in @@ -1199,6 +1254,15 @@ let test_rollup_wrong_rejection = let* () = repeat parameters.finality_period (fun () -> Client.bake_for client) in + let*! commitment = + Rollup.get_commitment + ~hooks + ~block:"head" + ~level:0 + ~rollup:state.rollup + client + in + let commitment = assert_some commitment in (* This is the encoding of [batch]. *) let message = batch in let*! _ = RPC.Tx_rollup.get_state ~rollup client in @@ -1211,6 +1275,17 @@ let test_rollup_wrong_rejection = ~position:0 client in + let proof = + {|{ "version": 3, + "before": { "node": "CoVu7Pqp1Gh3z33mink5T5Q2kAQKtnn3GHxVhyehdKZpQMBxFBGF" } , + "after": { "node": "CoUeJrcPBj3T3iJL3PY4jZHnmZa5rRZ87VQPdSBNBcwZRMWJGh9j" } , + "state": [] }|} + in + let* hash = + generate_prerejection ~rollup ~level:0 ~message_position:0 ~proof + in + let*! () = submit_prerejection ~hash state in + let* () = Client.bake_for client in let message_path = List.map (fun x -> JSON.as_string x) (JSON.as_list path) in let message_result_hash = Constant.tx_rollup_initial_message_result in let*! message_result_path = @@ -1225,11 +1300,7 @@ let test_rollup_wrong_rejection = Operation.inject_rejection ~source:Constant.bootstrap1 ~tx_rollup:state.rollup - ~proof: - {|{ "version": 3, - "before": { "node": "CoVu7Pqp1Gh3z33mink5T5Q2kAQKtnn3GHxVhyehdKZpQMBxFBGF" } , - "after": { "node": "CoUeJrcPBj3T3iJL3PY4jZHnmZa5rRZ87VQPdSBNBcwZRMWJGh9j" } , - "state": [] }|} + ~proof ~level:0 ~message ~message_position:0 @@ -1240,6 +1311,7 @@ let test_rollup_wrong_rejection = ~previous_message_context_hash:Constant.tx_rollup_empty_l2_context ~previous_message_withdraw_list_hash: Constant.tx_rollup_empty_withdraw_list_hash + ~commitment:commitment.commitment_hash state.client in let* () = Client.bake_for client in @@ -1297,6 +1369,19 @@ let test_rollup_wrong_path_for_rejection = client in let*! _ = RPC.Tx_rollup.get_state ~rollup client in + let* hash = + generate_prerejection + ~rollup + ~level:0 + ~message_position:0 + ~proof:Constant.tx_rollup_proof_initial_state + in + let*! () = submit_prerejection ~hash state in + let* () = Client.bake_for client in + let*! commitment = + Rollup.get_commitment ~hooks ~block:"head" ~level:0 ~rollup client + in + let commitment = assert_some commitment in let* (`OpHash _op) = Operation.inject_rejection ~source:Constant.bootstrap1 @@ -1312,6 +1397,7 @@ let test_rollup_wrong_path_for_rejection = ~previous_message_context_hash:Constant.tx_rollup_empty_l2_context ~previous_message_withdraw_list_hash: Constant.tx_rollup_empty_withdraw_list_hash + ~commitment:commitment.commitment_hash client in let* () = Client.bake_for client in @@ -1380,6 +1466,15 @@ let test_rollup_wrong_rejection_long_path = client in let agreed_message_result_path = "[]" in + let*! commitment = + Rollup.get_commitment + ~hooks + ~block:"head" + ~level:0 + ~rollup:state.rollup + client + in + let commitment = assert_some commitment in let*? process = Client.Tx_rollup.submit_rejection ~src:Constant.bootstrap1.alias @@ -1394,6 +1489,7 @@ let test_rollup_wrong_rejection_long_path = ~agreed_message_result_path ~context_hash:Constant.tx_rollup_empty_l2_context ~withdraw_list_hash:Constant.tx_rollup_empty_withdraw_list_hash + ~commitment:commitment.commitment_hash state.client in let* () = @@ -1401,6 +1497,15 @@ let test_rollup_wrong_rejection_long_path = ~msg:(rex "proto.alpha.tx_rollup_wrong_message_path_depth") process in + let* hash = + generate_prerejection + ~rollup:state.rollup + ~level:0 + ~message_position:0 + ~proof:Constant.tx_rollup_proof_initial_state + in + let*! () = submit_prerejection ~hash state in + let* () = Client.bake_for client in (* We check here the path is valid but the operation is rejected for a different reason. *) let*? process = @@ -1418,6 +1523,7 @@ let test_rollup_wrong_rejection_long_path = ~context_hash:Constant.tx_rollup_empty_l2_context ~withdraw_list_hash:Constant.tx_rollup_empty_withdraw_list_hash state.client + ~commitment:commitment.commitment_hash in Process.check_error ~msg:(rex "proto.alpha.tx_rollup_wrong_message_path") diff --git a/tezt/tests/tx_rollup_node.ml b/tezt/tests/tx_rollup_node.ml index 7b03625bf5c5..b3f9dff308ff 100644 --- a/tezt/tests/tx_rollup_node.ml +++ b/tezt/tests/tx_rollup_node.ml @@ -33,6 +33,10 @@ module Rollup = Rollup.Tx_rollup module Rollup_node = Rollup_node.Tx_node +let assert_some o = match o with None -> assert false | Some o -> o + +let assert_ok r = match r with Error _ -> assert false | Ok r -> r + let get_block_hash block_json = JSON.(block_json |-> "hash" |> as_string) let get_rollup_parameter_file ~protocol = @@ -154,6 +158,35 @@ let init_and_run_rollup_node ~operator ?batch_signer ?finalize_commitment_signer let* () = Rollup_node.wait_for_ready tx_node in Lwt.return (tx_rollup_hash, tx_node) +(** Generate and submit a prerejection for a given rejection proof *) +let prereject ~message_position ~source ~tx_rollup_hash ~client ~level proof_str + = + let open Tezos_protocol_alpha.Protocol.Alpha_context in + let prerejection = + Tx_rollup_rejection.generate_prerejection + ~source:(Tezos_crypto.Signature.Public_key_hash.of_b58check_exn source) + ~tx_rollup:(assert_some @@ Tx_rollup.of_b58check_opt tx_rollup_hash) + ~level:(assert_ok @@ Tx_rollup_level.of_int32 level) + ~message_position + ~proof: + (Data_encoding.Json.destruct + Tezos_protocol_alpha.Protocol.Tx_rollup_l2_proof.encoding + @@ assert_ok + @@ Data_encoding.Json.from_string proof_str) + in + let prerejection_str = + Tx_rollup_rejection.Rejection_hash.to_b58check prerejection + in + let*? process = + Client.Tx_rollup.submit_prerejection + ~hash:prerejection_str + ~rollup:tx_rollup_hash + ~src:source + client + in + let* () = Process.check process in + Client.bake_for client + (* Checks that the tx_node is ready after originating an associated rollup key. *) let test_tx_node_origination = @@ -1473,6 +1506,7 @@ let test_l2_proof_rpc_position = in return (JSON.encode agreed_message_result_path) in + let* { proof; message; @@ -1492,6 +1526,23 @@ let test_l2_proof_rpc_position = ~agreed_message_result_path commitment_info in + let* () = + prereject + ~client + ~source:operator + ~message_position:0 + ~tx_rollup_hash + ~level:1l + proof + in + let*! commitment = + Rollup.get_commitment + ~block:"head" + ~level:0 + ~rollup:tx_rollup_hash + client + in + let commitment = assert_some commitment in let*? process = Client.Tx_rollup.submit_rejection ~src:operator @@ -1506,6 +1557,7 @@ let test_l2_proof_rpc_position = ~context_hash ~withdraw_list_hash ~agreed_message_result_path + ~commitment:commitment.commitment_hash client in let* () = @@ -1533,6 +1585,17 @@ let test_l2_proof_rpc_position = ~agreed_message_result_path commitment_info in + Format.printf "trying prereject\n" ; + let* () = + prereject + ~client + ~source:operator + ~message_position:1 + ~tx_rollup_hash + ~level:1l + proof + in + Format.printf "done prereject\n" ; let*? process = Client.Tx_rollup.submit_rejection ~src:operator @@ -1547,6 +1610,7 @@ let test_l2_proof_rpc_position = ~context_hash ~withdraw_list_hash ~agreed_message_result_path + ~commitment:commitment.commitment_hash client in let* () = @@ -1617,6 +1681,23 @@ let test_reject_bad_commitment = ~client commitment_info in + let*! commitment = + Rollup.get_commitment + ~block:"head" + ~level:0 + ~rollup:tx_rollup_hash + client + in + let commitment = assert_some commitment in + let* () = + prereject + ~client + ~source:operator + ~message_position:0 + ~tx_rollup_hash + ~level:0l + proof + in let*! () = Client.Tx_rollup.submit_rejection ~src:operator @@ -1631,6 +1712,7 @@ let test_reject_bad_commitment = ~context_hash ~withdraw_list_hash ~agreed_message_result_path + ~commitment:commitment.commitment_hash client in unit) -- GitLab