diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 2a86acdc0896633741f6f40e570248a5fe1c5289..580a1a3eea5339ff17d0c38a82f332636b63829d 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -186,6 +186,7 @@ "Sc_rollup_errors", "Sc_rollup_inbox_storage", + "Remove_zero_amount_ticket_migration_for_o", "Legacy_script_patches", "Sapling_validator", diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index b7f947e6275e054f081bbda47eed2a2916e0e3ec..043637c7cd4bcaa703180358bdb02840ac6ae69b 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -200,6 +200,7 @@ Liquidity_baking_migration Sc_rollup_errors Sc_rollup_inbox_storage + Remove_zero_amount_ticket_migration_for_o Legacy_script_patches Sapling_validator Global_constants_storage @@ -490,6 +491,7 @@ liquidity_baking_migration.ml liquidity_baking_migration.mli sc_rollup_errors.ml sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + remove_zero_amount_ticket_migration_for_o.ml legacy_script_patches.ml sapling_validator.ml global_constants_storage.ml global_constants_storage.mli @@ -781,6 +783,7 @@ liquidity_baking_migration.ml liquidity_baking_migration.mli sc_rollup_errors.ml sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + remove_zero_amount_ticket_migration_for_o.ml legacy_script_patches.ml sapling_validator.ml global_constants_storage.ml global_constants_storage.mli @@ -1056,6 +1059,7 @@ liquidity_baking_migration.ml liquidity_baking_migration.mli sc_rollup_errors.ml sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + remove_zero_amount_ticket_migration_for_o.ml legacy_script_patches.ml sapling_validator.ml global_constants_storage.ml global_constants_storage.mli diff --git a/src/proto_alpha/lib_protocol/remove_zero_amount_ticket_migration_for_o.ml b/src/proto_alpha/lib_protocol/remove_zero_amount_ticket_migration_for_o.ml new file mode 100644 index 0000000000000000000000000000000000000000..8566f5fa6444f3cb3bcc77e8cd9e2bab852e13c5 --- /dev/null +++ b/src/proto_alpha/lib_protocol/remove_zero_amount_ticket_migration_for_o.ml @@ -0,0 +1,180 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(* Remove zero tickets from big map with id 5696. This big map is found in the + storage of [KT1CnygLoKfJA66499U9ZQkL6ykUfzgruGfM]. The id can be looked up in + https://tzkt.io/KT1CnygLoKfJA66499U9ZQkL6ykUfzgruGfM/storage/ + + This procedure removes all keys with zero-amount tickets from the big-map. + We have compiled a list of hashes corresponding to keys of values with + zero-amount tickets. We also verify removal by pattern matching on the values + to make sure they contain zero-amount ticket values. +*) + +type error += + | Invalid_big_map_key of string + | Not_zero_ticket of Script_expr_hash.t + | Invalid_big_map_value of Script_expr_hash.t + +let () = + register_error_kind + `Permanent + ~id:"migration.invalid_big_map_key" + ~title:"Invalid big map key as a script expression hash" + ~description: + "As part of the protocol migration, a big map key was expected to be \ + parsed successfully into a script expression hash" + ~pp:(fun ppf key -> + Format.fprintf ppf "Unable to parse %s as a script expression hash" key) + Data_encoding.(obj1 (req "key" (string Plain))) + (function Invalid_big_map_key key -> Some key | _ -> None) + (fun key -> Invalid_big_map_key key) ; + register_error_kind + `Permanent + ~id:"migration.not_zero_ticket_key" + ~title:"A big map key is not mapping to any zero ticket" + ~description:"the value mapped to a big map key has an unexpected shape" + ~pp:(fun ppf key -> + Format.fprintf + ppf + "%a does not map to a zero ticket, key not found" + Script_expr_hash.pp + key) + Data_encoding.(obj1 (req "key" Script_expr_hash.encoding)) + (function Not_zero_ticket key -> Some key | _ -> None) + (fun key -> Not_zero_ticket key) ; + register_error_kind + `Permanent + ~id:"migration.zero_ticket_wrong_value" + ~title:"A big map key is mapped to an unexpected value" + ~description: + "As part of the protocol migration, a big map key was expected to be \ + mapping into a value which is of unexpected shape" + ~pp:(fun ppf key -> + Format.fprintf + ppf + "%a does not map to a zero ticket, unexpected shape" + Script_expr_hash.pp + key) + Data_encoding.(obj1 (req "key" Script_expr_hash.encoding)) + (function Invalid_big_map_value key -> Some key | _ -> None) + (fun key -> Invalid_big_map_value key) + +let remove_zero_ticket_entries ctxt = + let open Lwt_result_syntax in + let*? contract_to_clean = + Contract_repr.of_b58check "KT1CnygLoKfJA66499U9ZQkL6ykUfzgruGfM" + in + let big_map_to_clean = + Lazy_storage_kind.Big_map.Id.parse_z @@ Z.of_int 5696 + in + let*? keys_to_evict = + List.map_e + (fun key -> + match Script_expr_hash.of_b58check_opt key with + | Some key -> ok key + | None -> error (Invalid_big_map_key key)) + [ + "exprtXBtxJxCDEDETueKAFLL7r7vZtNEo1MHajpHba1djtGKqJzWd3"; + "exprtbuRhaGDS942BgZ1qFdD7HAKeBjPEqzRxgLQyWQ6HWxcaiLC2c"; + "exprtePxSLgrhJmTPZEePyFBmESLhaBUN1WodvLYy9xYhEYE6dKPLe"; + "exprtx9GaYz5Fy5ytiuYgSfJqeYqkxGgobust8U6dpCLaeZUMiitmg"; + "expru28t4XoyB61WuRQnExk3Kq8ssGv1ejgdo9XHxpTXoQjXTGw1Dg"; + "expru2fZALknjB4vJjmQBPkrs3dJZ5ytuzfmE9A7ScUk5opJiZQyiJ"; + "expru2riAFKURjHJ1vNpvsZGGw6z4wtTvbstXVuwQPj1MaTqKPeQ6z"; + "expruHoZDr8ioVhaAs495crYTprAYyC87CruEJ6HaS7diYV6qLARqQ"; + "expruMie2gfy5smMd81NtcvvWm4jD7ThUebw9hpF3N3apKVtxkVG9M"; + "expruc3QW7cdxrGurDJQa6k9QqMZjGkRDJahy2XNtBt9WQzC1yavJK"; + "exprud86wYL7inFCVHkF1Jcz8uMXVY7dnbzxVupyyknZjtDVmwoQTJ"; + "exprufYzeBTGn9733Ga8xEEmU4SsrSyDrzEip8V8hTBAG253T5zZQx"; + "exprum9tuHNvisMa3c372AFmCa27rmkbCGrhzMSprrxgJjzXhrKAag"; + "expruokt7oQ6dDHRvL4sURKUzfwJirR8FPHvpXwjgUD4KHhPWhDGbv"; + "expruom5ds2hVgjdTB877Fx3ZuWT5WUnw1H6kUZavVHcJFbCkcgo3x"; + "exprv2DPd1pV3GVSN2CgW7PPrAQUTuZAdeJphwToQrTNrxiJcWzvtX"; + "exprv65Czv5TnKyEWgBHjDztkCkc1FAVEPxZ3V3ocgvGjfXwjPLo8M"; + "exprv6S2KAvqAC18jDLYjaj1w9oc4ESdDGJkUZ63EpkqSTAz88cSYB"; + "exprvNg3VDBnhtTHvc75krAEYzz6vUMr3iU5jtLdxs83FbgTbZ9nFT"; + "exprvS7wNDHYKYZ19nj3ZUo7AAVMCDpTK3NNERFhqe5SJGCBL4pwFA"; + ] + in + let* initial_big_map_size = + Storage.Big_map.Total_bytes.get ctxt big_map_to_clean + in + let* initial_storage_size = + Storage.Contract.Used_storage_space.get ctxt contract_to_clean + in + let scan_and_remove (ctxt, storage_freed) key = + let* ctxt, v = Storage.Big_map.Contents.get (ctxt, big_map_to_clean) key in + let open Micheline in + let open Michelson_v1_primitives in + match root v with + | Prim + ( _, + D_Pair, + [ + _timestamp; + Prim + ( _, + D_Pair, + [_data; Prim (_, D_Pair, [_ticketer; Int (_, amount)], _)], + _ ); + ], + _ ) -> + if Z.(equal amount zero) then + let* ctxt, size_sub, is_evicted = + Storage.Big_map.Contents.remove (ctxt, big_map_to_clean) key + in + if is_evicted then + return (ctxt, Z.(add storage_freed (Z.of_int size_sub))) + else tzfail @@ Invalid_big_map_value key + else tzfail @@ Invalid_big_map_value key + | _ -> tzfail @@ Invalid_big_map_value key + in + let* ctxt, storage_freed = + List.fold_left_es scan_and_remove (ctxt, Z.zero) keys_to_evict + in + let new_big_map_size = Z.sub initial_big_map_size storage_freed in + let* ctxt = + Storage.Big_map.Total_bytes.update ctxt big_map_to_clean new_big_map_size + in + let new_storage_size = Z.sub initial_storage_size storage_freed in + Storage.Contract.Used_storage_space.update + ctxt + contract_to_clean + new_storage_size + +let remove_zero_ticket_entries orig_ctxt = + let open Lwt_syntax in + let* res = remove_zero_ticket_entries orig_ctxt in + match res with + | Error e -> + Logging.( + log + Warning + "Error while removing zero tickets: %a" + Error_monad.pp_trace + e) ; + return orig_ctxt + | Ok ctxt -> return ctxt