diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index bc85d6ef6c593018bc9c7c01def92faa4ed9d5c6..286ee7758088336acad3c5d5733fadb01ab16ca1 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -32,6 +32,9 @@ Breaking Changes RPC Changes ----------- +- Add RPC to get contract's balance of ticket with specified ticketer, content type, and content: + ``POST /chains//blocks//context/contracts//ticket_balance``. (MR :gl:`!6488`) + Operation receipts ------------------ diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index e0c8d5a1e1c57a0f534e7a299b054af8c9330b9e..5d18d7f875c6818cfab0a8e22dfc4e90869334b8 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -533,7 +533,7 @@ let pp_ticket_receipt ppf ticket_receipt = updates in let pp_item ppf {ticket_token; updates} = - let {ticketer; contents_type; contents} = ticket_token in + let Ticket_token.{ticketer; contents_type; contents} = ticket_token in Format.fprintf ppf "Ticketer: %a@,Content type: %a@,Content: %a@,%a" diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index d4175efb1af9b5084c7bae0a5f4f88e671617ed2..ff6f6b65c0c04eb5d670500b27560bcd408d0833 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -1698,6 +1698,17 @@ module Contract = struct ~query:RPC_query.empty ~output:(option z) RPC_path.(path /: Contract.rpc_arg / "storage" / "paid_space") + + let ticket_balance = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the contract's balance of ticket with specified ticketer, \ + content type, and content." + ~query:RPC_query.empty + ~input:Ticket_token.unparsed_token_encoding + ~output:n + RPC_path.(path /: Contract.rpc_arg / "ticket_balance") end let get_contract contract f = @@ -1756,7 +1767,22 @@ module Contract = struct S.get_paid_storage_space (fun ctxt contract () () -> get_contract contract @@ fun _ -> - Contract.paid_storage_space ctxt contract >>=? return_some) + Contract.paid_storage_space ctxt contract >>=? return_some) ; + Registration.register1 + ~chunked:false + S.ticket_balance + (fun ctxt contract () Ticket_token.{ticketer; contents_type; contents} -> + let open Lwt_result_syntax in + let* ticket_hash, ctxt = + Ticket_balance_key.make + ctxt + ~owner:(Contract contract) + ~ticketer + ~contents_type:(Micheline.root contents_type) + ~contents:(Micheline.root contents) + in + let* amount, _ctxt = Ticket_balance.get_balance ctxt ticket_hash in + return @@ Option.value amount ~default:Z.zero) let get_storage_normalized ctxt block ~contract ~unparsing_mode = RPC_context.make_call1 @@ -1794,6 +1820,9 @@ module Contract = struct (Contract.Originated contract) () () + + let ticket_balance ctxt block contract key = + RPC_context.make_call1 S.ticket_balance ctxt block contract () key end module Big_map = struct diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 35182bbcdc57121b6400b72ee4f2af12cd110490..a6fbc9a7f5b1de9fe6c45f76e76fddfedabf8870 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -106,7 +106,6 @@ "Migration_repr", "Carbonated_map_costs", "Carbonated_map", - "Ticket_receipt_repr", "Raw_context_intf", "Raw_context", @@ -204,6 +203,8 @@ "Michelson_v1_gas", "Script_list", "Script_tc_context", + "Ticket_token", + "Ticket_receipt", "Apply_operation_result", "Apply_internal_results", "Apply_results", @@ -215,7 +216,6 @@ "Script_tc_errors_registration", "Ticket_costs", "Ticket_scanner", - "Ticket_token", "Ticket_balance_key", "Ticket_lazy_storage_diff", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 032c6b2ffc2c3225aba09f8d0fbb73a39b034a63..1edf9aa6825f185bbacf2ed3754c09c395bf6bbe 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -609,10 +609,6 @@ module Ticket_balance = struct include Ticket_storage end -module Ticket_receipt = struct - include Ticket_receipt_repr -end - module Token = Token module Cache = Cache_repr diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9a3e7fafaf5b5d537e6fbf4a5a5337ac2ef8910e..c0496c62d1bd2aa237ed14a9d3543ae9fa7868e6 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4910,25 +4910,6 @@ module Ticket_balance : sig end end -(** This module re-exports definitions from {!Ticket_receipt_repr}. *) -module Ticket_receipt : sig - type update = {account : Destination.t; amount : Z.t} - - type ticket_token = { - ticketer : Contract.t; - contents_type : Script.expr; - contents : Script.expr; - } - - type item = {ticket_token : ticket_token; updates : update list} - - type t = item list - - val item_encoding : item Data_encoding.t - - val encoding : t Data_encoding.t -end - module First_level_of_protocol : sig (** Get the level of the first block of this protocol. *) val get : context -> Raw_level.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 71cc2bda7be357b6911df85a9d0fa59df1aaee05..2051f19cbe62dfcf8aa798519fe3ff73a4cf0788 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -452,7 +452,7 @@ let apply_transaction_to_tx_rollup ~ctxt ~parameters_ty ~parameters ~payer {payload_size = ticket_size; limit}) >>=? fun () -> let ex_token, ticket_amount = - Ticket_token.token_and_amount_of_ex_ticket ex_ticket + Ticket_scanner.ex_token_and_amount_of_ex_ticket ex_ticket in Ticket_balance_key.of_ex_token ctxt ~owner:(Tx_rollup dst_rollup) ex_token >>=? fun (ticket_hash, ctxt) -> diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index b53da12c6614c4b1843968f3e638c45d8d25312d..fb09c19b20f2f0c6e4092912ffbf364453e0411b 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -132,7 +132,6 @@ Migration_repr Carbonated_map_costs Carbonated_map - Ticket_receipt_repr Raw_context_intf Raw_context Storage_costs @@ -218,6 +217,8 @@ Michelson_v1_gas Script_list Script_tc_context + Ticket_token + Ticket_receipt Apply_operation_result Apply_internal_results Apply_results @@ -229,7 +230,6 @@ Script_tc_errors_registration Ticket_costs Ticket_scanner - Ticket_token Ticket_balance_key Ticket_lazy_storage_diff Tx_rollup_parameters @@ -398,7 +398,6 @@ migration_repr.ml migration_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli - ticket_receipt_repr.ml ticket_receipt_repr.mli raw_context_intf.ml raw_context.ml raw_context.mli storage_costs.ml storage_costs.mli @@ -485,6 +484,8 @@ michelson_v1_gas.ml michelson_v1_gas.mli script_list.ml script_list.mli script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli apply_operation_result.ml apply_operation_result.mli apply_internal_results.ml apply_internal_results.mli apply_results.ml apply_results.mli @@ -496,7 +497,6 @@ script_tc_errors_registration.ml script_tc_errors_registration.mli ticket_costs.ml ticket_costs.mli ticket_scanner.ml ticket_scanner.mli - ticket_token.ml ticket_token.mli ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli @@ -645,7 +645,6 @@ migration_repr.ml migration_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli - ticket_receipt_repr.ml ticket_receipt_repr.mli raw_context_intf.ml raw_context.ml raw_context.mli storage_costs.ml storage_costs.mli @@ -732,6 +731,8 @@ michelson_v1_gas.ml michelson_v1_gas.mli script_list.ml script_list.mli script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli apply_operation_result.ml apply_operation_result.mli apply_internal_results.ml apply_internal_results.mli apply_results.ml apply_results.mli @@ -743,7 +744,6 @@ script_tc_errors_registration.ml script_tc_errors_registration.mli ticket_costs.ml ticket_costs.mli ticket_scanner.ml ticket_scanner.mli - ticket_token.ml ticket_token.mli ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli @@ -897,7 +897,6 @@ migration_repr.ml migration_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli - ticket_receipt_repr.ml ticket_receipt_repr.mli raw_context_intf.ml raw_context.ml raw_context.mli storage_costs.ml storage_costs.mli @@ -984,6 +983,8 @@ michelson_v1_gas.ml michelson_v1_gas.mli script_list.ml script_list.mli script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli apply_operation_result.ml apply_operation_result.mli apply_internal_results.ml apply_internal_results.mli apply_results.ml apply_results.mli @@ -995,7 +996,6 @@ script_tc_errors_registration.ml script_tc_errors_registration.mli ticket_costs.ml ticket_costs.mli ticket_scanner.ml ticket_scanner.mli - ticket_token.ml ticket_token.mli ticket_balance_key.ml ticket_balance_key.mli ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli tx_rollup_parameters.ml tx_rollup_parameters.mli diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_accounting.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_accounting.ml index 2a9b1945703d1388cae295083957ef7a8d0f20c3..ac711717acdd8a8669efd8e8467f0ca47548b1a9 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_accounting.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_accounting.ml @@ -121,7 +121,7 @@ let assert_equal_ticket_receipt ~loc given expected = @@ let*? ticketer = Contract.of_b58check ticketer in let contents = Expr.from_string (Printf.sprintf "%S" content) in let contents_type = Expr.from_string "string" in - let ticket_token = Ticket_receipt.{ticketer; contents_type; contents} in + let ticket_token = Ticket_token.{ticketer; contents_type; contents} in let updates = List.map (fun (account, amount) -> diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_manager.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_manager.ml index f8984e995394d7a700cccc8437983a23281bd4ec..711a6974ec7a05869e3fa190f6614fd3073a7afe 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_manager.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_manager.ml @@ -56,7 +56,9 @@ let init_env () = let collect_token_amounts ctxt tickets = let accum (tokens, ctxt) ticket = - let token, amount = Ticket_token.token_and_amount_of_ex_ticket ticket in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in let tokens = (token, Script_int.(to_zint (amount :> n num))) :: tokens in return (tokens, ctxt) in diff --git a/src/proto_alpha/lib_protocol/ticket_accounting.ml b/src/proto_alpha/lib_protocol/ticket_accounting.ml index 33d7aeaff5947545b478b5da9490d8521a70d3cc..3019d07dca0314d794480bb42f2a86442f3bc7d6 100644 --- a/src/proto_alpha/lib_protocol/ticket_accounting.ml +++ b/src/proto_alpha/lib_protocol/ticket_accounting.ml @@ -78,7 +78,9 @@ let ticket_balances_of_value ctxt ~include_lazy ty value = >>=? fun (tickets, ctxt) -> List.fold_left_e (fun (acc, ctxt) ticket -> - let token, amount = Ticket_token.token_and_amount_of_ex_ticket ticket in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step >|? fun ctxt -> ( (token, Script_int.to_zint (amount :> Script_int.n Script_int.num)) diff --git a/src/proto_alpha/lib_protocol/ticket_balance_key.ml b/src/proto_alpha/lib_protocol/ticket_balance_key.ml index bdc4b2675d39343013a8b3daf7d3e358d928fbc2..915f803d1f7f3a9c5117e9f266b18991ccf85549 100644 --- a/src/proto_alpha/lib_protocol/ticket_balance_key.ml +++ b/src/proto_alpha/lib_protocol/ticket_balance_key.ml @@ -26,6 +26,37 @@ open Alpha_context +let make ctxt ~owner ~ticketer ~contents_type ~contents = + let open Lwt_result_syntax in + let ticketer_address = + Script_typed_ir. + {destination = Contract ticketer; entrypoint = Entrypoint.default} + in + let owner_address = + Script_typed_ir.{destination = owner; entrypoint = Entrypoint.default} + in + let* ticketer, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized_legacy + Script_typed_ir.address_t + ticketer_address + in + let* owner, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized_legacy + Script_typed_ir.address_t + owner_address + in + Lwt.return + @@ Ticket_hash.make + ctxt + ~ticketer:(Micheline.root ticketer) + ~ty:contents_type + ~contents + ~owner:(Micheline.root owner) + (* This function extracts nodes of: - Ticketer - Type of content @@ -49,29 +80,9 @@ let of_ex_token ctxt ~owner contents_type contents >>=? fun (contents, ctxt) -> - let ticketer_address = - Script_typed_ir. - {destination = Contract ticketer; entrypoint = Entrypoint.default} - in - let owner_address = - Script_typed_ir.{destination = owner; entrypoint = Entrypoint.default} - in - Script_ir_translator.unparse_data + make ctxt - Script_ir_unparser.Optimized_legacy - Script_typed_ir.address_t - ticketer_address - >>=? fun (ticketer, ctxt) -> - Script_ir_translator.unparse_data - ctxt - Script_ir_unparser.Optimized_legacy - Script_typed_ir.address_t - owner_address - >>=? fun (owner, ctxt) -> - Lwt.return - (Ticket_hash.make - ctxt - ~ticketer:(Micheline.root ticketer) - ~ty - ~contents:(Micheline.root contents) - ~owner:(Micheline.root owner)) + ~owner + ~ticketer + ~contents_type:ty + ~contents:(Micheline.root contents) diff --git a/src/proto_alpha/lib_protocol/ticket_balance_key.mli b/src/proto_alpha/lib_protocol/ticket_balance_key.mli index f3160da53d1d3ab9e565ad10135b67fe2dfc6853..53af20ca9ada962c0dfdf91fbd9ca49a6bb70dcb 100644 --- a/src/proto_alpha/lib_protocol/ticket_balance_key.mli +++ b/src/proto_alpha/lib_protocol/ticket_balance_key.mli @@ -30,6 +30,18 @@ open Alpha_context global ticket-balance table that tracks ownership of tickets for different tokens. *) +(** [make ~owner ~ticketer ~contents_type ~contents] returns [key_hash] of the + given [owner], [ticketer], [contents_type] and [contents]. Note that the + [location] of the [Script.node] values [contents_type] and [contents] are + irrelevant since [Ticket_hash.make] will strip the locations before calculating the hash. *) +val make : + context -> + owner:Destination.t -> + ticketer:Contract.t -> + contents_type:Script.node -> + contents:Script.node -> + (Ticket_hash.t * context) tzresult Lwt.t + (** [of_ex_token ctxt ~owner ex_token] returns the [key_hash] of the given [owner] and [ex_token]. *) val of_ex_token : diff --git a/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml b/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml index abc4fb54e37fde0ef24b29ba55ce2cf7c8091ca2..cb4005939c5f4f71a74d8d5320bcd05c1ebc8d04 100644 --- a/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml +++ b/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml @@ -51,7 +51,9 @@ let () = let token_and_amount ctxt ex_ticket = Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step >|? fun ctxt -> - let token, amount = Ticket_token.token_and_amount_of_ex_ticket ex_ticket in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ex_ticket + in ((token, Script_int.(to_zint (amount :> n num))), ctxt) (** Extracts the ticket-token and amount from an ex_ticket value and returns diff --git a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml index 01f67f8fea7b5b16748ad7a9defdf7d4b260d83e..e4fff65f597f8271935a9cb48fcce184926c345e 100644 --- a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml +++ b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml @@ -239,7 +239,7 @@ let add_transfer_to_token_map ctxt token_map {destination; tickets} = List.fold_left_es (fun (token_map, ctxt) ticket -> let ticket_token, amount = - Ticket_token.token_and_amount_of_ex_ticket ticket + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket in Ticket_token_map.add ctxt ~ticket_token ~destination ~amount token_map) (token_map, ctxt) diff --git a/src/proto_alpha/lib_protocol/ticket_receipt_repr.ml b/src/proto_alpha/lib_protocol/ticket_receipt.ml similarity index 75% rename from src/proto_alpha/lib_protocol/ticket_receipt_repr.ml rename to src/proto_alpha/lib_protocol/ticket_receipt.ml index 6b2c836a287fe858b75c574a7042b876eae7e232..8f16bf97db825e5f80bcf7cba73ee9b34c0ce3c1 100644 --- a/src/proto_alpha/lib_protocol/ticket_receipt_repr.ml +++ b/src/proto_alpha/lib_protocol/ticket_receipt.ml @@ -23,15 +23,11 @@ (* *) (*****************************************************************************) -type update = {account : Destination_repr.t; amount : Z.t} +open Alpha_context -type ticket_token = { - ticketer : Contract_repr.t; - contents_type : Script_repr.expr; - contents : Script_repr.expr; -} +type update = {account : Destination.t; amount : Z.t} -type item = {ticket_token : ticket_token; updates : update list} +type item = {ticket_token : Ticket_token.unparsed_token; updates : update list} type t = item list @@ -40,19 +36,7 @@ let update_encoding = conv (fun {account; amount} -> (account, amount)) (fun (account, amount) -> {account; amount}) - (obj2 (req "account" Destination_repr.encoding) (req "amount" z)) - -let ticket_token_encoding = - let open Data_encoding in - conv - (fun {ticketer; contents_type; contents} -> - (ticketer, contents_type, contents)) - (fun (ticketer, contents_type, contents) -> - {ticketer; contents_type; contents}) - (obj3 - (req "ticketer" Contract_repr.encoding) - (req "content_type" Script_repr.expr_encoding) - (req "content" Script_repr.expr_encoding)) + (obj2 (req "account" Destination.encoding) (req "amount" z)) let item_encoding = let open Data_encoding in @@ -60,7 +44,7 @@ let item_encoding = (fun {ticket_token; updates} -> (ticket_token, updates)) (fun (ticket_token, updates) -> {ticket_token; updates}) (obj2 - (req "ticket_token" ticket_token_encoding) + (req "ticket_token" Ticket_token.unparsed_token_encoding) (req "updates" (list update_encoding))) let encoding = Data_encoding.list item_encoding diff --git a/src/proto_alpha/lib_protocol/ticket_receipt_repr.mli b/src/proto_alpha/lib_protocol/ticket_receipt.mli similarity index 89% rename from src/proto_alpha/lib_protocol/ticket_receipt_repr.mli rename to src/proto_alpha/lib_protocol/ticket_receipt.mli index e3c6e30a08f694dc6d756ae5b5aebdd8f1a6bf4e..d1397553d26a845910b4cf382e4da80ea4598c4b 100644 --- a/src/proto_alpha/lib_protocol/ticket_receipt_repr.mli +++ b/src/proto_alpha/lib_protocol/ticket_receipt.mli @@ -23,21 +23,16 @@ (* *) (*****************************************************************************) +open Alpha_context + (** A module for representing the increase/decrease of tickets in the storage. It will be used to display ticket update information in the operation receipt. *) (** Represents that [account]'s storage has delta [amount] for a given ticket *) -type update = {account : Destination_repr.t; amount : Z.t} - -(** A ticket token *) -type ticket_token = { - ticketer : Contract_repr.t; - contents_type : Script_repr.expr; - contents : Script_repr.expr; -} +type update = {account : Destination.t; amount : Z.t} (** List of updates for a [ticket] *) -type item = {ticket_token : ticket_token; updates : update list} +type item = {ticket_token : Ticket_token.unparsed_token; updates : update list} (** A list of ticket tokens and their corresponding updates *) type t = item list diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.ml b/src/proto_alpha/lib_protocol/ticket_scanner.ml index ec48d66213db22c4449d1023fd2f42289a182239..04075d107f457631896a3dd35a300a82559ac993 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.ml +++ b/src/proto_alpha/lib_protocol/ticket_scanner.ml @@ -557,3 +557,7 @@ let ex_ticket_size ctxt (Ex_ticket (ty, ticket)) = Gas.consume ctxt val_size_cost >>?= fun ctxt -> (* gas *) return (Saturation_repr.add ty_size val_size, ctxt) + +let ex_token_and_amount_of_ex_ticket + (Ex_ticket (contents_type, {Script_typed_ir.ticketer; contents; amount})) = + (Ticket_token.Ex_token {ticketer; contents_type; contents}, amount) diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.mli b/src/proto_alpha/lib_protocol/ticket_scanner.mli index c76c2830fe4b8f0b7f62f83e0bcc7aa593739101..90521e3f3e1de89b4bc48e13e240cda7fbc10eb2 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.mli +++ b/src/proto_alpha/lib_protocol/ticket_scanner.mli @@ -99,3 +99,8 @@ val ex_ticket_size : (Saturation_repr.may_saturate Saturation_repr.t * Alpha_context.context) tzresult Lwt.t + +(** [ex_token_and_amount_of_ex_ticket ex_ticket] returns the token and amount of + the given ticket [ex_ticket]. *) +val ex_token_and_amount_of_ex_ticket : + ex_ticket -> Ticket_token.ex_token * Script_typed_ir.ticket_amount diff --git a/src/proto_alpha/lib_protocol/ticket_token.ml b/src/proto_alpha/lib_protocol/ticket_token.ml index 2e495f30acf63c47c2c0e190762da463850f8ae4..ebf39367f0fe2f3cc08262e66b85d5bb5606f9ab 100644 --- a/src/proto_alpha/lib_protocol/ticket_token.ml +++ b/src/proto_alpha/lib_protocol/ticket_token.ml @@ -25,15 +25,28 @@ open Alpha_context -type ex_token = - | Ex_token : { - ticketer : Contract.t; - contents_type : 'a Script_typed_ir.comparable_ty; - contents : 'a; - } - -> ex_token +type 'a parsed_token = { + ticketer : Contract.t; + contents_type : 'a Script_typed_ir.comparable_ty; + contents : 'a; +} -let token_and_amount_of_ex_ticket - (Ticket_scanner.Ex_ticket - (contents_type, {Script_typed_ir.ticketer; contents; amount})) = - (Ex_token {ticketer; contents_type; contents}, amount) +type ex_token = Ex_token : 'a parsed_token -> ex_token + +type unparsed_token = { + ticketer : Contract.t; + contents_type : Script.expr; + contents : Script.expr; +} + +let unparsed_token_encoding = + let open Data_encoding in + conv + (fun {ticketer; contents_type; contents} -> + (ticketer, contents_type, contents)) + (fun (ticketer, contents_type, contents) -> + {ticketer; contents_type; contents}) + (obj3 + (req "ticketer" Contract.encoding) + (req "content_type" Script.expr_encoding) + (req "content" Script.expr_encoding)) diff --git a/src/proto_alpha/lib_protocol/ticket_token.mli b/src/proto_alpha/lib_protocol/ticket_token.mli index 6a4c655ac1892c8d8a74ef320f1528bd220d375b..b79865fadbf07b1bbd50214de35940811925de29 100644 --- a/src/proto_alpha/lib_protocol/ticket_token.mli +++ b/src/proto_alpha/lib_protocol/ticket_token.mli @@ -30,17 +30,22 @@ open Alpha_context a ticket comprises a ticket-token and an amount. *) +type 'a parsed_token = { + ticketer : Contract.t; + contents_type : 'a Script_typed_ir.comparable_ty; + contents : 'a; +} + (** A type for representing existentially quantified ticket-tokens. A ticket-token consists of a pair of ticketer and contents. *) -type ex_token = - | Ex_token : { - ticketer : Contract.t; - contents_type : 'a Script_typed_ir.comparable_ty; - contents : 'a; - } - -> ex_token +type ex_token = Ex_token : 'a parsed_token -> ex_token + +(** Unparsed version of [parsed_token]. + Used to encode/decode ticket-token in receipt, RPC, etc. *) +type unparsed_token = { + ticketer : Contract.t; + contents_type : Script.expr; + contents : Script.expr; +} -(** [token_and_amount_of_ex_ticket ex_ticket] returns the token and amount of - the given ticket [ex_ticket]. *) -val token_and_amount_of_ex_ticket : - Ticket_scanner.ex_ticket -> ex_token * Script_typed_ir.ticket_amount +val unparsed_token_encoding : unparsed_token Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/ticket_token_map.ml b/src/proto_alpha/lib_protocol/ticket_token_map.ml index 99f9d7e280d5664789167c01bc77b6a45b632777..9daab389c4f8a581bdbca274f0f6c38711b04a36 100644 --- a/src/proto_alpha/lib_protocol/ticket_token_map.ml +++ b/src/proto_alpha/lib_protocol/ticket_token_map.ml @@ -140,7 +140,7 @@ let to_ticket_receipt ctxt ~owner ticket_token_map = let ty = Script.strip_annotations ty_unstripped in let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost ty) in let contents_type = Micheline.strip_locations ty in - let ticket_token = Ticket_receipt.{ticketer; contents_type; contents} in + let ticket_token = Ticket_token.{ticketer; contents_type; contents} in let update = Ticket_receipt.{ticket_token; updates = [{account = owner; amount}]} in diff --git a/src/proto_alpha/lib_protocol/zk_rollup_apply.ml b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml index c5b9e070db7030eab41d6611cd6bf4449e3831d9..c2ab9534c372d1a6d4670dd41fe3f3bf608e596e 100644 --- a/src/proto_alpha/lib_protocol/zk_rollup_apply.ml +++ b/src/proto_alpha/lib_protocol/zk_rollup_apply.ml @@ -188,7 +188,7 @@ let transaction_to_zk_rollup ~ctxt ~parameters_ty ~parameters ~dst_rollup ~since {payload_size = ticket_size; limit}) in let ex_token, ticket_amount = - Ticket_token.token_and_amount_of_ex_ticket ex_ticket + Ticket_scanner.ex_token_and_amount_of_ex_ticket ex_ticket in (* Compute the ticket hash with zk rollup as owner *) let* ticket_hash, ctxt = diff --git a/tezt/lib_tezos/RPC.ml b/tezt/lib_tezos/RPC.ml index 21027cdae4743aa9465b984f93bfcd5f02d243c9..c0bc5fed69ba01b108ba164eef805dfcebca09d2 100644 --- a/tezt/lib_tezos/RPC.ml +++ b/tezt/lib_tezos/RPC.ml @@ -703,6 +703,23 @@ let get_chain_block_context_contract_storage ?(chain = "main") ?(block = "head") ["chains"; chain; "blocks"; block; "context"; "contracts"; id; "storage"] Fun.id +let post_chain_block_context_contract_ticket_balance ?(chain = "main") + ?(block = "head") ~id ~data () = + make + POST + [ + "chains"; + chain; + "blocks"; + block; + "context"; + "contracts"; + id; + "ticket_balance"; + ] + ~data + JSON.as_int + let get_chain_block_context_sc_rollup ?(chain = "main") ?(block = "head") () = make GET ["chains"; chain; "blocks"; block; "context"; "sc_rollup"] Fun.id diff --git a/tezt/lib_tezos/RPC.mli b/tezt/lib_tezos/RPC.mli index ec4ea6364cbaaa6592f2ee63ca0c0126bea3e167..e0b687151302791b1742bbbded767584fde4485c 100644 --- a/tezt/lib_tezos/RPC.mli +++ b/tezt/lib_tezos/RPC.mli @@ -728,6 +728,14 @@ val get_chain_block_context_contract_script : val get_chain_block_context_contract_storage : ?chain:string -> ?block:string -> id:string -> unit -> JSON.t t +(** RPC [POST /chains//blocks//context/contracts//ticket_balance] + + [chain] defaults to ["main"]. + [block] defaults to ["head"]. +*) +val post_chain_block_context_contract_ticket_balance : + ?chain:string -> ?block:string -> id:string -> data:JSON.u -> unit -> int t + (** {2 Smart contract rollup RPC module} *) (** RPC: [GET chains//blocks//context/sc_rollup] *) diff --git a/tezt/tests/expected/ticket_updates_in_receipt.ml/Alpha- Ticket updates in receipt.out b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out similarity index 100% rename from tezt/tests/expected/ticket_updates_in_receipt.ml/Alpha- Ticket updates in receipt.out rename to tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index 8198ec646e1e836812f710d476ad305f37045985..dcf83b7f77561a67695acbc22a2148733145a740 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -135,7 +135,7 @@ let register_protocol_agnostic_tests () = Synchronisation_heuristic.register ~protocols:[Alpha] ; Tenderbake.register ~protocols:[Alpha] ; Test_contract_bls12_381.register ~protocols:[Alpha] ; - Ticket_updates_in_receipt.register ~protocols:[Alpha] ; + Ticket_receipt_and_rpc.register ~protocols:[Alpha] ; Timelock.register ~protocols ; Tickets.register ~protocols ; Tx_rollup.register ~protocols ; diff --git a/tezt/tests/ticket_updates_in_receipt.ml b/tezt/tests/ticket_receipt_and_rpc.ml similarity index 69% rename from tezt/tests/ticket_updates_in_receipt.ml rename to tezt/tests/ticket_receipt_and_rpc.ml index b3ec40212edc25c91a5fabf745de0f347720e38b..492acdf189977d510412bd02a0fb5443e0f273d5 100644 --- a/tezt/tests/ticket_updates_in_receipt.ml +++ b/tezt/tests/ticket_receipt_and_rpc.ml @@ -26,12 +26,36 @@ (* Testing ------- Component: Michelson - Invocation: dune exec tezt/tests/main.exe -- --file ticket_updates_in_receipt.ml - Subject: Regression tests for ticket updates in receipt + Invocation: dune exec tezt/tests/main.exe -- --file ticket_receipt_and_rpc.ml + Subject: Regression tests for ticket receipt and ticket RPC *) let hooks = Tezos_regression.hooks +let check_ticket_balance client ~contract ~ticketer ~content_type ~content + ~expected = + let post_body = + Ezjsonm.value_from_string + @@ sf + {|{"ticketer": "%s", "content_type": {"prim": "%s"}, "content": {"string": "%s"}}|} + ticketer + content_type + content + in + let* actual = + RPC.Client.call client + @@ RPC.post_chain_block_context_contract_ticket_balance + ~id:contract + ~data:post_body + () + in + return + @@ Check.( + (actual = expected) + int + ~__LOC__ + ~error_msg:"expected ticket amount %R, got %L") + (* Checks how the ticket updates in receipt look like in various cases, such as: - Contract stores multiple tickets of different types. - Contract stores multiple tickets of the same type. @@ -51,14 +75,14 @@ let hooks = Tezos_regression.hooks tz_a -> KT_A (store 1 red and 2 green) *) -let test_ticket_updates_in_receipt = +let test_ticket_receipt_and_rpc = Protocol.register_regression_test ~__FILE__ ~title:"Ticket updates in receipt" ~tags:["client"; "michelson"] @@ fun protocol -> let* client = Client.init_mockup ~protocol () in - let* create_and_send = + let* kt_a = Client.originate_contract ~alias:"tickets_create_and_send.tz" ~amount:Tez.zero @@ -68,7 +92,7 @@ let test_ticket_updates_in_receipt = ~burn_cap:Tez.one client in - let* store_fst_and_rely_snd = + let* kt_b = Client.originate_contract ~alias:"tickets_store_fst_and_rely_snd.tz" ~amount:Tez.zero @@ -79,7 +103,7 @@ let test_ticket_updates_in_receipt = ~burn_cap:Tez.one client in - let* receive_and_store = + let* kt_c = Client.originate_contract ~alias:"tickets_receive_and_store.tz" ~amount:Tez.one @@ -95,15 +119,57 @@ let test_ticket_updates_in_receipt = ~burn_cap:(Tez.of_int 2) ~amount:Tez.zero ~giver:"bootstrap2" - ~receiver:create_and_send - ~arg: - (Format.sprintf - {|(Pair "%s" "%s")|} - store_fst_and_rely_snd - receive_and_store) + ~receiver:kt_a + ~arg:(Format.sprintf {|(Pair "%s" "%s")|} kt_b kt_c) ~hooks client in + (* Check that the ticket balance are expected via [ticket_balance] RPC. *) + let* () = + check_ticket_balance + client + ~contract:kt_a + ~ticketer:kt_a + ~content_type:"string" + ~content:"red" + ~expected:1 + in + let* () = + check_ticket_balance + client + ~contract:kt_a + ~ticketer:kt_a + ~content_type:"string" + ~content:"green" + ~expected:2 + in + let* () = + check_ticket_balance + client + ~contract:kt_a + ~ticketer:kt_a + ~content_type:"string" + ~content:"blue" + ~expected:0 + in + let* () = + check_ticket_balance + client + ~contract:kt_b + ~ticketer:kt_a + ~content_type:"string" + ~content:"blue" + ~expected:1 + in + let* () = + check_ticket_balance + client + ~contract:kt_c + ~ticketer:kt_a + ~content_type:"string" + ~content:"blue" + ~expected:1 + in unit -let register ~protocols = test_ticket_updates_in_receipt protocols +let register ~protocols = test_ticket_receipt_and_rpc protocols