diff --git a/docs/alpha/michelson.rst b/docs/alpha/michelson.rst index 9d37863c945bd29eaa72ce1a2c5bf6f77d10f31a..bfadf2f4222fc368a08093db89ed3053ca37a3ca 100644 --- a/docs/alpha/michelson.rst +++ b/docs/alpha/michelson.rst @@ -2304,11 +2304,11 @@ This process can happen without the need to interact with a centralized NFT cont simplifying the code. - ``TICKET``: Create a ticket with the given content and amount. The ticketer is the address - of `SELF`. + of `SELF`. The resulting value is ``NONE`` if the amount is zero. :: - :: 'a : nat : 'S -> ticket 'a : 'S + :: 'a : nat : 'S -> option ticket 'a : 'S Type ``'a`` must be comparable (the ``COMPARE`` primitive must be defined over it). @@ -2322,7 +2322,7 @@ Type ``'a`` must be comparable (the ``COMPARE`` primitive must be defined over i same content and ticketer as the original, but with the new provided amounts. (This can be used to easily implement UTXOs.) Return None iff the ticket's original amount is not equal to the sum of the - provided amounts. + provided amounts, or one of the provided amounts is zero. :: diff --git a/docs/alpha/transaction_rollups.rst b/docs/alpha/transaction_rollups.rst index 5c937986add16528df06b7a396681b9ac7946798..b3270031a1aa547572daeee07050214c4073270b 100644 --- a/docs/alpha/transaction_rollups.rst +++ b/docs/alpha/transaction_rollups.rst @@ -203,6 +203,7 @@ tickets to a Transaction Rollup:: PUSH nat 10; PUSH unit Unit; TICKET; + ASSERT_SOME; PAIR ; @@ -723,6 +724,7 @@ rollup can be found in the integration tests of the feature.:: CAR; UNPAIR 4; TICKET; + ASSERT_SOME; PAIR; SWAP; CONTRACT %deposit (pair (ticket string) tx_rollup_l2_address); diff --git a/docs/kathmandu/michelson.rst b/docs/kathmandu/michelson.rst index 779f9cb05b14565f686a92c492a94a1ec5f1a005..4b38be14f38406bbd6a0086d7dfd15d92f3766cd 100644 --- a/docs/kathmandu/michelson.rst +++ b/docs/kathmandu/michelson.rst @@ -2310,7 +2310,7 @@ Type ``'a`` must be comparable (the ``COMPARE`` primitive must be defined over i same content and ticketer as the original, but with the new provided amounts. (This can be used to easily implement UTXOs.) Return None iff the ticket's original amount is not equal to the sum of the - provided amounts. + provided amounts, or one of the provided amounts is zero. :: diff --git a/docs/michelson/michelson-meta.yaml b/docs/michelson/michelson-meta.yaml index ad64c8e8b15bc4a988779b0e4149d52de0346c2c..be0f550b55a1d74375d90130844cbee2c43c5ef0 100644 --- a/docs/michelson/michelson-meta.yaml +++ b/docs/michelson/michelson-meta.yaml @@ -1725,7 +1725,9 @@ instructions: proposed-in: ['PtEdoTezd3RHSC31mpxxo1npxFjoWWcFgQtxapi51Z8TLu6v6Uq'] documentation_short: Create a ticket documentation: | - Create a ticket with the given content and amount. The ticketer is the address of ``SELF``. + Creates a value ``Some t`` where ``t`` is a ticket with the given content and amount. + The ticketer is the address of ``SELF``. + Returns ``None`` iff the amount is zero. READ_TICKET: category: tickets diff --git a/docs/michelson/michelson.ott b/docs/michelson/michelson.ott index 1657e0e0d6e7272259fea65e459f613589cf43c2..2c3423eeb490b9e0108f1bf00a5ab9db6f9452d4 100644 --- a/docs/michelson/michelson.ott +++ b/docs/michelson/michelson.ott @@ -1099,7 +1099,7 @@ Typing :: 't_' ::= ------------------------------------------------ :: TICKET - ctx :- TICKET :: cty : nat : A => ticket cty : A + ctx :- TICKET :: cty : nat : A => option ( ticket cty ) : A ------------------------------------------------ :: READ_TICKET ctx :- READ_TICKET :: ticket cty : A => pair address cty nat : ticket cty : A @@ -2259,8 +2259,13 @@ UNPACK ty / byt : S => unpack ty byt : S % tickets: -------------------------------------------------- :: TICKET -TICKET / x : n : S => Pair (address self) x n : S +n = 0 +------------------------------------------------- :: TICKET_zero +TICKET / x : n : S => None : S + +n <> 0 +------------------------------------------------- :: TICKET_nonzero +TICKET / x : n : S => Some (Pair (address self) x n) : S ----------------------------------------------------------- :: READ_TICKET READ_TICKET / Pair s x n : S => Pair s x n : Pair s x n : S diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 529363514f9754be3c333a833eb127de23afd6a9..7b9e6a80001625db43cb3e9b0945717d7b64bc39 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -196,6 +196,12 @@ Breaking Changes safer version of timelock will come in a future procotol. (MR :gl: `!6260`) - Rename the parameter ``tokens_per_roll`` to ``minimal_stake``. (MR :gl:`!5897`) +- Disallow creation, transfer and storage of tickets with zero amounts. + ``TICKET`` instruction now returns ``option ticket 'a`` instead of ``ticket 'a``. + For contracts already originated, their ``TICKET`` instructions are renamed to ``TICKET_DEPRECATED``. + Note that it is not possible to originate contracts containing ``TICKET_DEPRECATED`` + after the migration. + (MR :gl:`!5963`) RPC Changes ----------- diff --git a/src/proto_alpha/lib_benchmark/michelson_samplers.ml b/src/proto_alpha/lib_benchmark/michelson_samplers.ml index f36ab8c661e02e3b5e117ca57a7cf415e63e8b62..f57dc510d4ee81a97ed4fbe2a72f568c03cf6786 100644 --- a/src/proto_alpha/lib_benchmark/michelson_samplers.ml +++ b/src/proto_alpha/lib_benchmark/michelson_samplers.ml @@ -803,7 +803,12 @@ end) let ticketer = Alpha_context.Contract.Implicit (Crypto_samplers.pkh rng_state) in - let amount = Michelson_base.nat rng_state in + let amount = + let open Ticket_amount in + match of_n (Michelson_base.nat rng_state) with + | Some amount -> add amount one + | None -> one + in Script_typed_ir.{ticketer; contents; amount} let comparable ty = value ty diff --git a/src/proto_alpha/lib_benchmarks_proto/interpreter_benchmarks.ml b/src/proto_alpha/lib_benchmarks_proto/interpreter_benchmarks.ml index cb9c98c540df0eb7f73c167d3b22a6ffae982d06..4dee5096896adea44d83396441345863f2110aba 100644 --- a/src/proto_alpha/lib_benchmarks_proto/interpreter_benchmarks.ml +++ b/src/proto_alpha/lib_benchmarks_proto/interpreter_benchmarks.ml @@ -2848,7 +2848,7 @@ module Registration_section = struct Alpha_context.Contract.Implicit Environment.Signature.Public_key_hash.zero; contents = (); - amount = zero; + amount = Ticket_amount.one; } in benchmark_with_fixed_stack @@ -2868,7 +2868,13 @@ module Registration_section = struct in fun () -> let half_amount = Samplers.Random_value.value nat rng_state in + let half_amount = Script_int.add_n half_amount Script_int.one_n in let amount = Script_int.add_n half_amount half_amount in + let amount = + (* this is safe because half_amount > 0 *) + WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_n amount + in let ticket = Samplers.Random_value.value (ticket unit) rng_state in let ticket = {ticket with amount} in Ex_stack_and_kinstr @@ -2903,7 +2909,7 @@ module Registration_section = struct { ticket with contents = Script_string.empty; - amount = Script_int.zero_n; + amount = Ticket_amount.one; } in Ex_stack_and_kinstr @@ -2925,7 +2931,13 @@ module Registration_section = struct let ticket = Samplers.Random_value.value (ticket string) rng_state in - let alt_amount = Samplers.Random_value.value nat rng_state in + let alt_amount = + let amount = Samplers.Random_value.value nat rng_state in + let open Ticket_amount in + match of_n amount with + | Some amount -> add amount one + | None -> one + in let ticket' = {ticket with amount = alt_amount} in Ex_stack_and_kinstr { diff --git a/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml b/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml index 17146ea2f3052ba84b70f6b3ce3f41c6902e5a68..a2826fa847bf28d547930c0a46698a39f8e51645 100644 --- a/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml +++ b/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml @@ -1417,15 +1417,16 @@ let extract_ir_sized_step : | IComb_get (_, n, _, _), _ -> Instructions.comb_get (Size.of_int n) | IComb_set (_, n, _, _), _ -> Instructions.comb_set (Size.of_int n) | IDup_n (_, n, _, _), _ -> Instructions.dupn (Size.of_int n) - | ITicket (_, _, _), _ -> Instructions.ticket + | ITicket (_, _, _), _ | ITicket_deprecated (_, _, _), _ -> + Instructions.ticket | IRead_ticket (_, _, _), _ -> Instructions.read_ticket | ISplit_ticket (_, _), (_ticket, ((amount_a, amount_b), _)) -> Instructions.split_ticket (Size.integer amount_a) (Size.integer amount_b) | IJoin_tickets (_, cmp_ty, _), ((ticket1, ticket2), _) -> let size1 = Size.size_of_comparable_value cmp_ty ticket1.contents in let size2 = Size.size_of_comparable_value cmp_ty ticket2.contents in - let tez1 = Size.integer ticket1.amount in - let tez2 = Size.integer ticket2.amount in + let tez1 = Size.integer (ticket1.amount :> Script_int.n Script_int.num) in + let tez2 = Size.integer (ticket2.amount :> Script_int.n Script_int.num) in Instructions.join_tickets size1 size2 tez1 tez2 | IHalt _, _ -> Instructions.halt | ILog _, _ -> Instructions.log diff --git a/src/proto_alpha/lib_benchmarks_proto/ticket_benchmarks.ml b/src/proto_alpha/lib_benchmarks_proto/ticket_benchmarks.ml index 6b1e614378b1146a45068b5597e9803312d1958c..3a472f44fca2abc8f4fde34eac18035a160672ad 100644 --- a/src/proto_alpha/lib_benchmarks_proto/ticket_benchmarks.ml +++ b/src/proto_alpha/lib_benchmarks_proto/ticket_benchmarks.ml @@ -251,7 +251,7 @@ let ticket_sampler rng_state = let pkh, _, _ = Signature.generate_key ~algo:Signature.Ed25519 ~seed () in let ticketer = Alpha_context.Contract.Implicit pkh in Script_typed_ir. - {ticketer; contents = Script_int.zero; amount = Script_int.one_n} + {ticketer; contents = Script_int.zero; amount = Ticket_amount.one} (** A benchmark for {!Ticket_costs.Constants.cost_collect_tickets_step}. *) module Collect_tickets_benchmark : Benchmark.S = struct @@ -285,7 +285,6 @@ module Collect_tickets_benchmark : Benchmark.S = struct (Ticket_scanner.tickets_of_value ctxt ~include_lazy:true - ~allow_zero_amount_tickets:true has_tickets boxed_ticket_list)) in diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index 7830269d141ff1606e0e79b197ffc4267e7d9cc5..382300861838e2adda82931ae9c1f2c129026273 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -792,7 +792,7 @@ val transfer_ticket : contents:string -> ty:string -> ticketer:Contract.t -> - amount:Z.t -> + amount:Ticket_amount.t -> destination:Contract.t -> entrypoint:Entrypoint.t -> unit -> diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 4c0173dff9948de5bc2e6bceaf5d956e9b225b3c..d178952cef64c9c6f3fd36e88c90d97b5d3e33a3 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -305,7 +305,7 @@ let pp_manager_operation_content (type kind) source ppf Contract.pp ticketer Z.pp_print - amount + Script_int.(to_zint (amount :> n num)) Contract.pp destination (fun ppf entrypoint -> 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 39b34b34cc9b9e1c596bed061f79d92c8405ba9a..7393c2ecee14b5337f22e103501c3968c6619e19 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 @@ -2876,31 +2876,34 @@ let commands_rw () = cctxt -> let open Lwt_result_syntax in let* _, src_pk, src_sk = Client_keys.get_key cctxt source in - let* _res = - transfer_ticket - cctxt - ~chain:cctxt#chain - ~block:cctxt#block - ~dry_run - ~verbose_signing - ?fee - ?storage_limit - ?counter - ?confirmations:cctxt#confirmations - ~simulation - ~source - ~src_pk - ~src_sk - ~fee_parameter - ~contents - ~ty - ~ticketer - ~amount - ~destination - ~entrypoint - () - in - return_unit); + match Ticket_amount.of_zint amount with + | Some amount -> + let* _res = + transfer_ticket + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~contents + ~ty + ~ticketer + ~amount + ~destination + ~entrypoint + () + in + return_unit + | None -> cctxt#error "ticket quantity should not be zero or negative"); command ~group ~desc:"Originate a new smart-contract rollup." diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 94b2c9a6d001df7e6c498710f0c5b5d6876f5655..f03f5b1ce3ecd20d5b85cc1f2e41433a6667c449 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -806,6 +806,7 @@ module Scripts = struct | IComb_set _ -> pp_print_string fmt "UPDATE" | IDup_n _ -> pp_print_string fmt "DUP" | ITicket _ -> pp_print_string fmt "TICKET" + | ITicket_deprecated _ -> pp_print_string fmt "TICKET_DEPRECATED" | IRead_ticket _ -> pp_print_string fmt "READ_TICKET" | ISplit_ticket _ -> pp_print_string fmt "SPLIT_TICKET" | IJoin_tickets _ -> pp_print_string fmt "JOIN_TICKETS" diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 4505a81b5a49df9f92488f1ed33a048e177f4013..fc3f11c8490536a1c301cfefe7eb8c9e5fe88d33 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -92,6 +92,8 @@ "Liquidity_baking_repr", "Block_header_repr", "Destination_repr", + "Script_int", + "Ticket_amount", "Operation_repr", "Manager_repr", "Commitment_repr", @@ -173,7 +175,6 @@ "Alpha_context", "Script_string", - "Script_int", "Script_timestamp", "Tx_rollup_l2_storage_sig", diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 02d9d09902aad65674fe6d1f750a0275250b04bb..a15e7045571c559e12ada98fc93f2c86393c31f6 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -633,6 +633,7 @@ module Script : sig | I_SHA3 | I_PAIRING_CHECK | I_TICKET + | I_TICKET_DEPRECATED | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS @@ -4215,7 +4216,7 @@ and _ manager_operation = contents : Script.lazy_expr; ty : Script.lazy_expr; ticketer : Contract.t; - amount : Z.t; + amount : Ticket_amount.t; destination : Contract.t; entrypoint : Entrypoint.t; } diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 44b611db0d48c40f6c9c0de289e163448ee6e075..d7698bb662487084bd7ad47f26908b2b6d445ee3 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -470,11 +470,13 @@ let apply_transaction_to_tx_rollup ~ctxt ~parameters_ty ~parameters ~payer Option.value_e ~error: (Error_monad.trace_of_error Tx_rollup_invalid_transaction_ticket_amount) - (Option.bind (Script_int.to_int64 ticket_amount) Tx_rollup_l2_qty.of_int64) + (Option.bind + (Script_int.to_int64 (ticket_amount :> Script_int.n Script_int.num)) + Tx_rollup_l2_qty.of_int64) >>?= fun ticket_amount -> error_when Tx_rollup_l2_qty.(ticket_amount <= zero) - Ticket_scanner.Forbidden_zero_ticket_quantity + Script_tc_errors.Forbidden_zero_ticket_quantity >>?= fun () -> let deposit, message_size = Tx_rollup_message.make_deposit @@ -820,7 +822,7 @@ let apply_manager_operation : Tx_rollup_reveal.{contents; ty; ticketer; amount; claimer} -> error_when Tx_rollup_l2_qty.(amount <= zero) - Ticket_scanner.Forbidden_zero_ticket_quantity + Script_tc_errors.Forbidden_zero_ticket_quantity >>?= fun () -> Tx_rollup_ticket.parse_ticket ~consume_deserialization_gas @@ -860,7 +862,13 @@ let apply_manager_operation : ( Tx_rollup_withdraw. {claimer; amount; ticket_hash = tx_rollup_ticket_hash}, ticket_token ) = - let amount = Tx_rollup_l2_qty.to_z amount in + Tx_rollup_l2_qty.to_z amount + |> Ticket_amount.of_zint + |> Option.value_e + ~error: + (Error_monad.trace_of_error + Script_tc_errors.Forbidden_zero_ticket_quantity) + >>?= fun amount -> Ticket_balance_key.of_ex_token ctxt ~owner:(Contract (Contract.Implicit claimer)) @@ -889,12 +897,6 @@ let apply_manager_operation : return (ctxt, result, []) | Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} -> ( - (* The encoding ensures that the amount is in a natural number. Here is - mainly to check that it is non-zero.*) - error_when - Compare.Z.(amount <= Z.zero) - Ticket_scanner.Forbidden_zero_ticket_quantity - >>?= fun () -> match destination with | Implicit _ -> fail Cannot_transfer_ticket_to_implicit | Originated destination_hash -> diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index af80c03b5f2e68d8cea394483df49076077ce968..aabf5f136dc6a762c0fb6429c8a302d284a2a7cc 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -118,6 +118,8 @@ Liquidity_baking_repr Block_header_repr Destination_repr + Script_int + Ticket_amount Operation_repr Manager_repr Commitment_repr @@ -189,7 +191,6 @@ Dal_slot_storage Alpha_context Script_string - Script_int Script_timestamp Tx_rollup_l2_storage_sig Tx_rollup_l2_context_sig @@ -377,6 +378,8 @@ liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli operation_repr.ml operation_repr.mli manager_repr.ml manager_repr.mli commitment_repr.ml commitment_repr.mli @@ -449,7 +452,6 @@ dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli - script_int.ml script_int.mli script_timestamp.ml script_timestamp.mli tx_rollup_l2_storage_sig.ml tx_rollup_l2_context_sig.ml @@ -617,6 +619,8 @@ liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli operation_repr.ml operation_repr.mli manager_repr.ml manager_repr.mli commitment_repr.ml commitment_repr.mli @@ -689,7 +693,6 @@ dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli - script_int.ml script_int.mli script_timestamp.ml script_timestamp.mli tx_rollup_l2_storage_sig.ml tx_rollup_l2_context_sig.ml @@ -862,6 +865,8 @@ liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli operation_repr.ml operation_repr.mli manager_repr.ml manager_repr.mli commitment_repr.ml commitment_repr.mli @@ -934,7 +939,6 @@ dal_slot_storage.ml dal_slot_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli - script_int.ml script_int.mli script_timestamp.ml script_timestamp.mli tx_rollup_l2_storage_sig.ml tx_rollup_l2_context_sig.ml diff --git a/src/proto_alpha/lib_protocol/michelson_v1_gas.ml b/src/proto_alpha/lib_protocol/michelson_v1_gas.ml index 6a578209dceafe01fc87409d15ed1b2ef8b046f4..92f5b0bcb210c70f24f41be8c62204293aa85480 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_gas.ml +++ b/src/proto_alpha/lib_protocol/michelson_v1_gas.ml @@ -1509,7 +1509,9 @@ module Cost_of = struct in Gas.( contents_comparison +@ compare_address - +@ add_nat ticket_a.amount ticket_b.amount) + +@ add_nat + (ticket_a.amount :> Script_int.n Script_int.num) + (ticket_b.amount :> Script_int.n Script_int.num)) let emit = atomic_step_cost cost_N_IEmit diff --git a/src/proto_alpha/lib_protocol/michelson_v1_gas.mli b/src/proto_alpha/lib_protocol/michelson_v1_gas.mli index f799d7d556400ed447e3c5ba910ced14b57a436a..9a06aacfc62924bc00411bfa4cd3f1f0fc0dea67 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_gas.mli +++ b/src/proto_alpha/lib_protocol/michelson_v1_gas.mli @@ -351,7 +351,10 @@ module Cost_of : sig val read_ticket : Gas.cost val split_ticket : - 'a Script_int.num -> 'a Script_int.num -> 'a Script_int.num -> Gas.cost + Script_typed_ir.ticket_amount -> + 'a Script_int.num -> + 'a Script_int.num -> + Gas.cost val join_tickets : 'a Script_typed_ir.comparable_ty -> diff --git a/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml b/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml index 118f5df397c8b77738d798093762e6044af90818..b8ae12fc1997c0fd30faed9607b4856ffaeade54 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml +++ b/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml @@ -149,6 +149,7 @@ type prim = | I_SHA3 | I_PAIRING_CHECK | I_TICKET + | I_TICKET_DEPRECATED | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS @@ -219,8 +220,9 @@ let namespace = function | I_SAPLING_VERIFY_UPDATE | I_SELF | I_SELF_ADDRESS | I_SENDER | I_SET_DELEGATE | I_SHA256 | I_SHA512 | I_SHA3 | I_SIZE | I_SLICE | I_SOME | I_SOURCE | I_SPLIT_TICKET | I_STEPS_TO_QUOTA | I_SUB | I_SUB_MUTEZ | I_SWAP - | I_TICKET | I_TOTAL_VOTING_POWER | I_TRANSFER_TOKENS | I_UNIT | I_UNPACK - | I_UNPAIR | I_UPDATE | I_VOTING_POWER | I_XOR | I_OPEN_CHEST | I_EMIT -> + | I_TICKET | I_TICKET_DEPRECATED | I_TOTAL_VOTING_POWER | I_TRANSFER_TOKENS + | I_UNIT | I_UNPACK | I_UNPAIR | I_UPDATE | I_VOTING_POWER | I_XOR + | I_OPEN_CHEST | I_EMIT -> Instr_namespace | T_address | T_tx_rollup_l2_address | T_big_map | T_bool | T_bytes | T_chain_id | T_contract | T_int | T_key | T_key_hash | T_lambda | T_list @@ -357,6 +359,7 @@ let string_of_prim = function | I_SHA3 -> "SHA3" | I_PAIRING_CHECK -> "PAIRING_CHECK" | I_TICKET -> "TICKET" + | I_TICKET_DEPRECATED -> "TICKET_DEPRECATED" | I_READ_TICKET -> "READ_TICKET" | I_SPLIT_TICKET -> "SPLIT_TICKET" | I_JOIN_TICKETS -> "JOIN_TICKETS" @@ -514,6 +517,7 @@ let prim_of_string = function | "VOTING_POWER" -> ok I_VOTING_POWER | "TOTAL_VOTING_POWER" -> ok I_TOTAL_VOTING_POWER | "TICKET" -> ok I_TICKET + | "TICKET_DEPRECATED" -> ok I_TICKET_DEPRECATED | "READ_TICKET" -> ok I_READ_TICKET | "SPLIT_TICKET" -> ok I_SPLIT_TICKET | "JOIN_TICKETS" -> ok I_JOIN_TICKETS @@ -746,7 +750,7 @@ let prim_encoding = ("ticket", T_ticket); (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) (* Alpha_008 addition *) - ("TICKET", I_TICKET); + ("TICKET_DEPRECATED", I_TICKET_DEPRECATED); ("READ_TICKET", I_READ_TICKET); ("SPLIT_TICKET", I_SPLIT_TICKET); ("JOIN_TICKETS", I_JOIN_TICKETS); @@ -770,7 +774,8 @@ let prim_encoding = ("EMIT", I_EMIT); (* Alpha_015 addition *) ("Lambda_rec", D_Lambda_rec); - ("LAMBDA_REC", I_LAMBDA_REC) + ("LAMBDA_REC", I_LAMBDA_REC); + ("TICKET", I_TICKET) (* New instructions must be added here, for backward compatibility of the encoding. *) (* Keep the comment above at the end of the list *); ] diff --git a/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli b/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli index 69660958351d2f8a36f373674f81ecfff341a4d1..349285c9c95852d50f3834074234bc7070040a96 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli +++ b/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli @@ -162,6 +162,7 @@ type prim = | I_SHA3 | I_PAIRING_CHECK | I_TICKET + | I_TICKET_DEPRECATED | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 386003470779d231c25b865e42f3d8eceedfd799..020ffe01b888c2a28e3e739797cf3c215de6b1b0 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -417,7 +417,7 @@ and _ manager_operation = contents : Script_repr.lazy_expr; ty : Script_repr.lazy_expr; ticketer : Contract_repr.t; - amount : Z.t; + amount : Ticket_amount.t; destination : Contract_repr.t; entrypoint : Entrypoint_repr.t; } @@ -1035,7 +1035,7 @@ module Encoding = struct (req "ticket_contents" Script_repr.lazy_expr_encoding) (req "ticket_ty" Script_repr.lazy_expr_encoding) (req "ticket_ticketer" Contract_repr.encoding) - (req "ticket_amount" n) + (req "ticket_amount" Ticket_amount.encoding) (req "destination" Contract_repr.encoding) (req "entrypoint" Entrypoint_repr.simple_encoding); select = diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index ce9e4cf2089e0a2e74db148ed6a2bfdf7fcedf1b..168184395c05305e1b6e20e4fb60e7440eb6de51 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -481,7 +481,7 @@ and _ manager_operation = ty : Script_repr.lazy_expr; (** Type of the withdrawn ticket's contents *) ticketer : Contract_repr.t; (** Ticketer of the withdrawn ticket *) - amount : Z.t; + amount : Ticket_amount.t; (** Quantity of the withdrawn ticket. Must match the amount that was enabled. *) destination : Contract_repr.t; diff --git a/src/proto_alpha/lib_protocol/sc_rollup_operations.ml b/src/proto_alpha/lib_protocol/sc_rollup_operations.ml index 36835da925d97670d061f9edfd9686685b5936c6..7929694841420fb3fdf3c2035096d7367e3c9277 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_operations.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_operations.ml @@ -339,13 +339,14 @@ let transfer_ticket_tokens ctxt ~source_destination ~acc_storage_diff {Ticket_operations_diff.ticket_token; total_amount = _; destinations} = let open Lwt_tzresult_syntax in List.fold_left_es - (fun (acc_storage_diff, ctxt) (target_destination, amount) -> + (fun (acc_storage_diff, ctxt) + (target_destination, (amount : Script_typed_ir.ticket_amount)) -> let* storage_diff, ctxt = transfer_ticket_token ctxt ~source_destination ~target_destination - ~amount:(Script_int.to_zint amount) + ~amount:Script_int.(to_zint (amount :> n num)) ticket_token in return (Z.(add acc_storage_diff storage_diff), ctxt)) @@ -480,10 +481,7 @@ let execute_outbox_message ctxt ~validate_and_decode_output_proof rollup as they cannot be tracked by the ticket-balance table. *) let* ticket_token_diffs, ctxt = - Ticket_operations_diff.ticket_diffs_of_operations - ctxt - ~allow_zero_amount_tickets:false - operations + Ticket_operations_diff.ticket_diffs_of_operations ctxt operations in (* Update the ticket-balance table by transferring ticket-tokens to new destinations for each transaction. This fails in case the rollup does not diff --git a/src/proto_alpha/lib_protocol/script_interpreter.ml b/src/proto_alpha/lib_protocol/script_interpreter.ml index 535d2e5c14bcc8b186593f7480c37bba6487736f..49d87067fc5ff1ec01ff4a0c88c9e95c3ceff3cf 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter.ml @@ -1479,24 +1479,41 @@ and step : type a s b t r f. (a, s, b, t, r, f) step_type = let accu = aux witness stack in (step [@ocaml.tailcall]) g gas k ks accu stack (* Tickets *) - | ITicket (_, _, k) -> + | ITicket_deprecated (_, _, k) -> ( let contents = accu and amount, stack = stack in - let ticketer = Contract.Originated sc.self in - let accu = {ticketer; contents; amount} in - (step [@ocaml.tailcall]) g gas k ks accu stack + match Ticket_amount.of_n amount with + | Some amount -> + let ticketer = Contract.Originated sc.self in + let accu = {ticketer; contents; amount} in + (step [@ocaml.tailcall]) g gas k ks accu stack + | None -> fail Script_tc_errors.Forbidden_zero_ticket_quantity) + | ITicket (_, _, k) -> ( + let contents = accu and amount, stack = stack in + match Ticket_amount.of_n amount with + | Some amount -> + let ticketer = Contract.Originated sc.self in + let accu = Some {ticketer; contents; amount} in + (step [@ocaml.tailcall]) g gas k ks accu stack + | None -> (step [@ocaml.tailcall]) g gas k ks None stack) | IRead_ticket (_, _, k) -> let {ticketer; contents; amount} = accu in let stack = (accu, stack) in let destination : Destination.t = Contract ticketer in let addr = {destination; entrypoint = Entrypoint.default} in - let accu = (addr, (contents, amount)) in + let accu = + (addr, (contents, (amount :> Script_int.n Script_int.num))) + in (step [@ocaml.tailcall]) g gas k ks accu stack | ISplit_ticket (_, k) -> let ticket = accu and (amount_a, amount_b), stack = stack in let result = + Option.bind (Ticket_amount.of_n amount_a) @@ fun amount_a -> + Option.bind (Ticket_amount.of_n amount_b) @@ fun amount_b -> + let amount = Ticket_amount.add amount_a amount_b in if Compare.Int.( - Script_int.(compare (add_n amount_a amount_b) ticket.amount) = 0) + Script_int.(compare (amount :> n num) (ticket.amount :> n num)) + = 0) then Some ( {ticket with amount = amount_a}, @@ -1520,7 +1537,7 @@ and step : type a s b t r f. (a, s, b, t, r, f) step_type = { ticketer = ticket_a.ticketer; contents = ticket_a.contents; - amount = Script_int.add_n ticket_a.amount ticket_b.amount; + amount = Ticket_amount.add ticket_a.amount ticket_b.amount; } else None in diff --git a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml index ca1c4d82f92fc7ec3287734665be6f4a29385635..ab0c2464303a201100d862a2dbde11d19ce67729 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml @@ -350,7 +350,7 @@ let cost_of_instr : type a s r f. (a, s, r, f) kinstr -> a -> s -> Gas.cost = | IUncomb (_, n, _, _) -> Interp_costs.uncomb n | IComb_get (_, n, _, _) -> Interp_costs.comb_get n | IComb_set (_, n, _, _) -> Interp_costs.comb_set n - | ITicket _ -> Interp_costs.ticket + | ITicket _ | ITicket_deprecated _ -> Interp_costs.ticket | IRead_ticket _ -> Interp_costs.read_ticket | IOpen_chest _ -> let _chest_key = accu and chest, (time, _) = stack in diff --git a/src/proto_alpha/lib_protocol/script_interpreter_logging.ml b/src/proto_alpha/lib_protocol/script_interpreter_logging.ml index 31f10c4f49d10461aae734c5c3f736e9f25da071..d09762eca53a06d5d9763f878460fc2fb9fc0dea 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter_logging.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter_logging.ml @@ -1545,7 +1545,7 @@ let kinstr_split : reconstruct = (fun k -> IDup_n (loc, n, p, k)); } | ITicket (loc, cty, k), Item_t (_, Item_t (_, s)) -> - ticket_t dummy (assert_some cty) >|? fun t -> + ticket_t dummy (assert_some cty) >>? option_t loc >|? fun t -> let s = Item_t (t, s) in Ex_split_kinstr { @@ -1553,6 +1553,15 @@ let kinstr_split : continuation = k; reconstruct = (fun k -> ITicket (loc, cty, k)); } + | ITicket_deprecated (loc, cty, k), Item_t (_, Item_t (_, s)) -> + ticket_t dummy (assert_some cty) >|? fun t -> + let s = Item_t (t, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ITicket_deprecated (loc, cty, k)); + } | IRead_ticket (loc, a, k), s -> pair_t dummy (assert_some a) nat_t >>? fun (Ty_ex_c p) -> pair_t dummy address_t p >|? fun (Ty_ex_c t) -> diff --git a/src/proto_alpha/lib_protocol/script_ir_translator.ml b/src/proto_alpha/lib_protocol/script_ir_translator.ml index 42db9ea6c7a40edfc613d05cc5fd1196d5d896a2..4f987a86ea9e37530283d00ceed79e053e2f27d5 100644 --- a/src/proto_alpha/lib_protocol/script_ir_translator.ml +++ b/src/proto_alpha/lib_protocol/script_ir_translator.ml @@ -2109,10 +2109,13 @@ let rec parse_data : opened_ticket_type (location expr) t >>?= fun ty -> non_terminal_recursion ctxt ty expr >>=? fun (({destination; entrypoint = _}, (contents, amount)), ctxt) -> - match destination with - | Contract ticketer -> return ({ticketer; contents; amount}, ctxt) - | Tx_rollup _ | Sc_rollup _ -> - fail (Unexpected_ticket_owner destination) + match Ticket_amount.of_n amount with + | Some amount -> ( + match destination with + | Contract ticketer -> return ({ticketer; contents; amount}, ctxt) + | Tx_rollup _ | Sc_rollup _ -> + fail (Unexpected_ticket_owner destination)) + | None -> traced_fail Forbidden_zero_ticket_quantity else traced_fail (Unexpected_forged_value (location expr)) (* Sets *) | Set_t (t, _ty_name), (Seq (loc, vs) as expr) -> @@ -4158,8 +4161,21 @@ and parse_instr : check_comparable loc t >>?= fun Eq -> ticket_t loc t >>?= fun res_ty -> let instr = {apply = (fun k -> ITicket (loc, for_logging_only t, k))} in + option_t loc res_ty >>?= fun res_ty -> let stack = Item_t (res_ty, rest) in typed ctxt loc instr stack + | Prim (loc, I_TICKET_DEPRECATED, [], annot), Item_t (t, Item_t (Nat_t, rest)) + -> + if legacy then + check_var_annot loc annot >>?= fun () -> + check_comparable loc t >>?= fun Eq -> + ticket_t loc t >>?= fun res_ty -> + let instr = + {apply = (fun k -> ITicket_deprecated (loc, for_logging_only t, k))} + in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + else fail (Deprecated_instruction I_TICKET_DEPRECATED) | ( Prim (loc, I_READ_TICKET, [], annot), (Item_t (Ticket_t (t, _), _) as full_stack) ) -> check_var_annot loc annot >>?= fun () -> diff --git a/src/proto_alpha/lib_protocol/script_ir_unparser.ml b/src/proto_alpha/lib_protocol/script_ir_unparser.ml index ef40e260e1d72e0d27a7d1cfb9791109641038ed..37300a1c019504fb9c8a5b9328473164f11904d3 100644 --- a/src/proto_alpha/lib_protocol/script_ir_unparser.ml +++ b/src/proto_alpha/lib_protocol/script_ir_unparser.ml @@ -544,7 +544,7 @@ module Data_unparser (P : MICHELSON_PARSER) = struct ~stack_depth mode t - (addr, (contents, amount)) + (addr, (contents, (amount :> Script_int.n Script_int.num))) | Set_t (t, _), set -> List.fold_left_es (fun (l, ctxt) item -> diff --git a/src/proto_alpha/lib_protocol/script_tc_errors.ml b/src/proto_alpha/lib_protocol/script_tc_errors.ml index 1f0c39d222b8bda47d16e6cd30e5bca766cbb951..ba465e11c33312fa15724f5320d4817b51e81c92 100644 --- a/src/proto_alpha/lib_protocol/script_tc_errors.ml +++ b/src/proto_alpha/lib_protocol/script_tc_errors.ml @@ -74,6 +74,8 @@ type error += Tx_rollup_bad_deposit_parameter of Script.location * Script.expr type error += Tx_rollup_invalid_ticket_amount of Z.t +type error += Forbidden_zero_ticket_quantity + type error += Tx_rollup_addresses_disabled of Script.location (* Smart-contract rollup errors *) diff --git a/src/proto_alpha/lib_protocol/script_tc_errors_registration.ml b/src/proto_alpha/lib_protocol/script_tc_errors_registration.ml index 70b586a528edb42f72d9a28b7fd7e8c357fefed5..3b873c9f6406fb6c070f019b543fc32dd2a4230d 100644 --- a/src/proto_alpha/lib_protocol/script_tc_errors_registration.ml +++ b/src/proto_alpha/lib_protocol/script_tc_errors_registration.ml @@ -254,6 +254,15 @@ let () = (obj1 (req "requested_value" Data_encoding.z)) (function Tx_rollup_invalid_ticket_amount z -> Some z | _ -> None) (fun z -> Tx_rollup_invalid_ticket_amount z) ; + register_error_kind + `Permanent + ~id:"michelson_v1.forbidden_zero_amount_ticket" + ~title:"Zero ticket amount is not allowed" + ~description: + "It is not allowed to use a zero amount ticket in this operation." + Data_encoding.empty + (function Forbidden_zero_ticket_quantity -> Some () | _ -> None) + (fun () -> Forbidden_zero_ticket_quantity) ; (* Tx rollup addresses disabled *) register_error_kind `Permanent diff --git a/src/proto_alpha/lib_protocol/script_typed_ir.ml b/src/proto_alpha/lib_protocol/script_typed_ir.ml index 94b3d4a4bdd9ec834a433e572575d368144dcc08..84ea1d401e25b20dd3fe2098ac39db5b138ddf18 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir.ml +++ b/src/proto_alpha/lib_protocol/script_typed_ir.ml @@ -217,7 +217,9 @@ module Script_timelock = struct let get_plaintext_size (Chest_tag x) = Timelock.get_plaintext_size x end -type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : n num} +type ticket_amount = Ticket_amount.t + +type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : ticket_amount} module type TYPE_SIZE = sig (* A type size represents the size of its type parameter. @@ -1063,6 +1065,11 @@ and ('before_top, 'before, 'result_top, 'result) kinstr = * ('t, 'a * ('b * 's), 'r, 'f) kinstr -> ('a, 'b * 's, 'r, 'f) kinstr | ITicket : + Script.location + * 'a comparable_ty option + * ('a ticket option, 's, 'r, 'f) kinstr + -> ('a, n num * 's, 'r, 'f) kinstr + | ITicket_deprecated : Script.location * 'a comparable_ty option * ('a ticket, 's, 'r, 'f) kinstr -> ('a, n num * 's, 'r, 'f) kinstr | IRead_ticket : @@ -1603,6 +1610,7 @@ let kinstr_location : type a s b f. (a, s, b, f) kinstr -> Script.location = | IComb_set (loc, _, _, _) -> loc | IDup_n (loc, _, _, _) -> loc | ITicket (loc, _, _) -> loc + | ITicket_deprecated (loc, _, _) -> loc | IRead_ticket (loc, _, _) -> loc | ISplit_ticket (loc, _) -> loc | IJoin_tickets (loc, _, _) -> loc @@ -2004,6 +2012,7 @@ let kinstr_traverse i init f = | IComb_set (_, _, _, k) -> (next [@ocaml.tailcall]) k | IDup_n (_, _, _, k) -> (next [@ocaml.tailcall]) k | ITicket (_, _, k) -> (next [@ocaml.tailcall]) k + | ITicket_deprecated (_, _, k) -> (next [@ocaml.tailcall]) k | IRead_ticket (_, _, k) -> (next [@ocaml.tailcall]) k | ISplit_ticket (_, k) -> (next [@ocaml.tailcall]) k | IJoin_tickets (_, _, k) -> (next [@ocaml.tailcall]) k diff --git a/src/proto_alpha/lib_protocol/script_typed_ir.mli b/src/proto_alpha/lib_protocol/script_typed_ir.mli index e7b46c89178396e908148c843fe1b574cfa54e90..8f37c9788e50710ecfa8d763e8f625f5a1db99b3 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir.mli +++ b/src/proto_alpha/lib_protocol/script_typed_ir.mli @@ -167,7 +167,9 @@ module Script_timelock : sig val get_plaintext_size : chest -> int end -type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : n num} +type ticket_amount = Ticket_amount.t + +type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : ticket_amount} type empty_cell = EmptyCell @@ -1060,6 +1062,11 @@ and ('before_top, 'before, 'result_top, 'result) kinstr = * ('t, 'a * ('b * 's), 'r, 'f) kinstr -> ('a, 'b * 's, 'r, 'f) kinstr | ITicket : + Script.location + * 'a comparable_ty option + * ('a ticket option, 's, 'r, 'f) kinstr + -> ('a, n num * 's, 'r, 'f) kinstr + | ITicket_deprecated : Script.location * 'a comparable_ty option * ('a ticket, 's, 'r, 'f) kinstr -> ('a, n num * 's, 'r, 'f) kinstr | IRead_ticket : diff --git a/src/proto_alpha/lib_protocol/script_typed_ir_size.ml b/src/proto_alpha/lib_protocol/script_typed_ir_size.ml index 58e525803b8a5db581c229a3f77fdf5b2a3ad79d..9f83611ff53bbbbbb36e005dac37445502af389b 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir_size.ml +++ b/src/proto_alpha/lib_protocol/script_typed_ir_size.ml @@ -214,7 +214,9 @@ let chain_id_size = !!16 (* by Obj.reachable_words. *) (* [contents] is handled by the recursion scheme in [value_size]. *) let ticket_size {ticketer; contents = _; amount} = - h3w +! Contract.in_memory_size ticketer +! script_nat_size amount + h3w + +! Contract.in_memory_size ticketer + +! script_nat_size (amount :> Script_int.n Script_int.num) let chest_size chest = (* @@ -653,6 +655,10 @@ and kinstr_size : ret_succ_adding accu (base1 loc k +! ty_for_logging_size cty +! word_size) + | ITicket_deprecated (loc, cty, k) -> + ret_succ_adding + accu + (base1 loc k +! ty_for_logging_size cty +! word_size) | IRead_ticket (loc, ty, k) -> ret_succ_adding accu (base1 loc k +! ty_for_logging_size ty +! word_size) | ISplit_ticket (loc, k) -> ret_succ_adding accu (base1 loc k) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 7eab0f71f8d2937a86b62089b08b154edd71fc9b..5415b242697f8a14f50b209a424739ad2a2fbbd7 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -756,8 +756,8 @@ let tx_rollup_dispatch_tickets ?force_reveal ?counter ?fee ?gas_limit sign account.sk ctxt to_sign_op let transfer_ticket ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt - ~(source : Contract.t) ~contents ~ty ~ticketer amount ~destination - entrypoint = + ~(source : Contract.t) ~contents ~ty ~ticketer ~amount ~destination + ~entrypoint = manager_operation ?force_reveal ?counter diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index 43be79111161e513d17d9765868016d8f3ef3353..a52e005b9df498d3d9c213cc72fe4fca5e78961f 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -528,9 +528,9 @@ val transfer_ticket : contents:Script.lazy_expr -> ty:Script.lazy_expr -> ticketer:Contract.t -> - Z.t -> + amount:Ticket_amount.t -> destination:Contract.t -> - Entrypoint_repr.t -> + entrypoint:Entrypoint_repr.t -> (packed_operation, tztrace) result Lwt.t (** [tx_rollup_reject ctxt source tx_rollup tx_rollup level message diff --git a/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml b/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml index d645e1bdb48c9cd8a6b3e60b48f4accd453c445b..58b381a5be0a1d5d229a00c5390865298c79ea28 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml @@ -643,7 +643,15 @@ let generate_transfer_ticket random_state : let ty = Script.lazy_expr (Expr.from_string "nat") in let ticketer = random_contract random_state in let destination = random_contract random_state in - let amount = random_counter random_state in + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_n + @@ Script_int.( + add_n one_n + @@ Option.value ~default:zero_n + @@ is_nat @@ of_zint + @@ random_counter random_state) + in let entrypoint = Entrypoint.default in Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} in 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 ed6156801acc745224e5ac0dd9f4c6a6bee0d5bb..d8857d475c72ef4909c2ce3a1eea5c91bd38230f 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 @@ -445,7 +445,10 @@ let assert_ticket_diffs ctxt ~loc ~arg_type ~storage_type ~arg ~old_storage let assert_balance = Ticket_helpers.assert_balance let string_ticket ticketer contents amount = - let amount = Script_int.abs @@ Script_int.of_int amount in + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_n @@ Script_int.abs @@ Script_int.of_int amount + in let ticketer = Result.value_f ~default:(fun _ -> assert false) @@ Contract.of_b58check ticketer diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_balance.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_balance.ml index f3d74a420ebbff1cbbdcf56e6b903a1e989b5be9..b8ae0972f0ef5d6ee529f405359f862355c04a61 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_balance.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_balance.ml @@ -204,6 +204,7 @@ let test_add_strict () = PUSH nat 1; PUSH string "Red"; TICKET; + ASSERT_SOME; CONS; NIL operation ; PAIR } } @@ -258,6 +259,7 @@ let test_add_remove () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; CONS ; NIL operation ; PAIR } @@ -322,6 +324,7 @@ let test_add_to_big_map () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; SOME ; DUP 3 ; GET_AND_UPDATE ; @@ -381,6 +384,7 @@ let test_swap_big_map () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; SOME ; DIG 3 ; GET_AND_UPDATE ; @@ -482,6 +486,7 @@ let test_send_tickets () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; TRANSFER_TOKENS ; PUSH unit Unit ; NIL operation ; @@ -532,6 +537,7 @@ let test_send_and_store_zero_amount_tickets () = DIG 2 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; TRANSFER_TOKENS ; PUSH unit Unit ; NIL operation ; @@ -616,15 +622,14 @@ let test_send_and_store_zero_amount_tickets () = "%store") in let token_red = string_token ~ticketer:ticket_minter "Red" in - (* Mint and send a ticket with amount 0 to [ticket_store_1]. After the - transaction: + (* Mint and send a ticket with amount 0 to [ticket_store_1], which fails. + After the transaction: [ticket_store_1]: - [ - (TM, "Red", 0) - ] + [ ] *) - let* block = mint_and_send_to_storer_1 block 0 in + let*! result = mint_and_send_to_storer_1 block 0 in + assert (Result.is_error result) ; let* () = assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None in @@ -634,7 +639,6 @@ let test_send_and_store_zero_amount_tickets () = [ticket_store_1]: [ (TM, "Red", 10) - (TM, "Red", 0) ] *) let* block = mint_and_send_to_storer_1 block 10 in @@ -645,9 +649,7 @@ let test_send_and_store_zero_amount_tickets () = ticket (TM, "Red", 10). After the transaction: ticket_store_1: - [ - (TM, "Red", 0) - ] + [ ] ticket_store_2: [ (TM, "Red", 10) @@ -660,18 +662,19 @@ let test_send_and_store_zero_amount_tickets () = let* () = assert_token_balance ~loc:__LOC__ block token_red ticket_store_2 (Some 10) in - (* Send the top of [ticket_store_1]'s stack to [ticket_store_2]. That is the - ticket (TM, "Red", 0). Now, [ticket_store_2] holds both tickets. + (* Send the top of [ticket_store_1]'s stack to [ticket_store_2]. + However, this fails because [ticket_store_1]'s stack is empty. + Now, [ticket_store_2] holds both tickets. ticket_store_1: [ ] [ticket_store_2]: [ (TM, "Red", 10) - (TM, "Red", 0) ] *) - let* block = send_from_store_1_to_store_2 block in + let*! result = send_from_store_1_to_store_2 block in + assert (Result.is_error result) ; let* () = assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None in @@ -688,7 +691,6 @@ let test_send_and_store_zero_amount_tickets () = [ticket_store_2]: [ (TM, "Red", 10) - (TM, "Red", 0) ] *) let* block = mint_and_send_to_storer_1 block 5 in @@ -705,7 +707,6 @@ let test_send_and_store_zero_amount_tickets () = [ (TM, "Red", 5) (TM, "Red", 10) - (TM, "Red", 0) ] *) let* block = send_from_store_1_to_store_2 block in @@ -754,6 +755,7 @@ let test_send_tickets_in_big_map () = PUSH nat 1 ; DIG 3 ; TICKET ; + ASSERT_SOME ; SOME ; DIG 2 ; GET_AND_UPDATE ; @@ -861,6 +863,7 @@ let test_modify_big_map () = PUSH nat 1 ; DIG 3 ; TICKET ; + ASSERT_SOME ; SOME ; DIG 2 ; GET_AND_UPDATE ; @@ -962,6 +965,7 @@ let test_send_tickets_in_big_map_and_drop () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 1 ; GET_AND_UPDATE ; @@ -1019,6 +1023,7 @@ let test_create_contract_with_ticket () = UNPAIR ; UNPAIR ; TICKET ; + ASSERT_SOME ; PUSH mutez 0 ; DIG 2 ; SOME ; @@ -1070,10 +1075,11 @@ let test_join_tickets () = code { CDR ; IF_NONE { PUSH nat 1 ; PUSH string "Red" ; - TICKET ; SOME ; NIL operation ; PAIR } + TICKET ; ASSERT_SOME ; SOME ; NIL operation ; PAIR } { PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; PAIR ; JOIN_TICKETS ; NIL operation ; @@ -1141,7 +1147,7 @@ let ticket_builder = DUP @manager 2; SENDER; ASSERT_CMPEQ; UNPAIR; - SWAP; UNIT; TICKET; + SWAP; UNIT; TICKET; ASSERT_SOME; PUSH mutez 0; SWAP; TRANSFER_TOKENS; NIL operation; SWAP; CONS }; @@ -1220,18 +1226,33 @@ let ticket_wallet = READ_TICKET; GET @total_amount 4; DUP @amount 5; - SWAP; SUB; ISNAT; ASSERT_SOME @remaining_amount; + SWAP; SUB; + DUP; EQ; + IF + { + # Drop @remaining_amount because it is zero + DROP; + # Drop @amount because this is now irrelevant + DIG 3; DROP; + # Drop @ticketer because we are not storing any ticket in this wallet + DIG 3; DROP; + # Bring the big map to the stack top since the ticket entry is already striked out + DUG 3 + } + { + ISNAT; ASSERT_SOME @remaining_amount; - # Split the ticket - DIG 4; PAIR; SWAP; SPLIT_TICKET; - ASSERT_SOME; UNPAIR @to_send @to_keep; + # Split the ticket + DIG 4; PAIR; SWAP; SPLIT_TICKET; + ASSERT_SOME; UNPAIR @to_send @to_keep; - # Store the ticket to keep - DUG 5; - SOME; - DIG 3; - GET_AND_UPDATE; - ASSERT_NONE; + # Store the ticket to keep + DUG 5; + SOME; + DIG 3; + GET_AND_UPDATE; + ASSERT_NONE; + }; DIG 2; PAIR; # Send the ticket @@ -1409,6 +1430,7 @@ let test_ticket_storage () = PUSH nat 1 ; PUSH string "Red" ; TICKET ; + ASSERT_SOME ; PAIR ; TRANSFER_TOKENS ; PUSH unit Unit ; @@ -1532,7 +1554,7 @@ let test_storage_for_create_and_remove_tickets () = storage (list (ticket string)) ; code { UNPAIR ; IF_LEFT - { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; CONS ; NIL operation ; PAIR } + { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; ASSERT_SOME ; CONS ; NIL operation ; PAIR } { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } |} ~storage:"{}" @@ -1556,22 +1578,22 @@ let test_storage_for_create_and_remove_tickets () = ~recipient:ticket_manager ~parameters:"Unit" in - (* Initially the used and paid contract storage size is 115. *) + (* Initially the used and paid contract storage size is 141. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 115 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 141 in let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 115 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 141 in (* Add 1000 units of "A" tickets. *) let* block = add block 1000 "A" in (* After adding one block the new used and paid storage grows to accommodate - for the new ticket. The size is 115 + 40 (size of ticket) = 155. *) + for the new ticket. The size is 141 + 40 (size of ticket) = 181. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 155 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 181 in let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 155 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 181 in (* The size of used and paid-for ticket storage is 67 bytes. (65 for hash and 2 for amount). *) @@ -1581,10 +1603,10 @@ let test_storage_for_create_and_remove_tickets () = let* block = add block 1000 "B" in (* The new used and paid for contract storage grow to 155 + 40 = 195. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 195 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 221 in let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 195 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 in (* The new used and paid for ticket storage doubles (2 * 67 = 134). *) let* () = assert_used_ticket_storage ~loc:__LOC__ block 134 in @@ -1594,10 +1616,10 @@ let test_storage_for_create_and_remove_tickets () = (* We're back to 115 base-line for the used contract storage and keep 195 for paid. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 115 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 141 in let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 195 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 in (* Since the ticket-table is empty it does not take up any space. However, we've already paid for 134 bytes. *) @@ -1605,14 +1627,14 @@ let test_storage_for_create_and_remove_tickets () = let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in (* Add one unit of "C" tickets. *) let* block = add block 1 "C" in - (* The new used storage is 115 + 39 (size of ticket) = 154. The size is 39 + (* The new used storage is 141 + 39 (size of ticket) = 180. The size is 39 rather than 40 because it carries a smaller amount payload. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 154 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 180 in - (* We still have paid for 195 contract storage. *) + (* We still have paid for 221 contract storage. *) let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 195 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 in (* There is one row in the ticket table with size 65 (for the hash) + 1 (for the amount) = 65 bytes. *) @@ -1621,13 +1643,13 @@ let test_storage_for_create_and_remove_tickets () = let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in (* Add yet another "C" ticket. *) let* block = add block 1 "C" in - (* The new used storage is 154 + 39 (size of ticket) = 193. *) + (* The new used storage is 180 + 39 (size of ticket) = 219. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 193 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 219 in - (* We still have paid for 195 contract storage. *) + (* We still have paid for 221 contract storage. *) let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 195 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 in (* There is still only one row in the ticket table with size 66. *) let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in @@ -1635,26 +1657,26 @@ let test_storage_for_create_and_remove_tickets () = let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in (* Add a "D" ticket. *) let* block = add block 1 "D" in - (* The new used storage is 193 + 39 (size of ticket) = 193. *) + (* The new used storage is 219 + 39 (size of ticket) = 258. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 232 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 258 in - (* The paid storage also increases to 232. *) + (* The paid storage also increases to 258. *) let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 232 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 258 in (* There are now two rows in the ticket table: 2 x 66 = 132 *) let* () = assert_used_ticket_storage ~loc:__LOC__ block 132 in (* And we've still paid for 134 bytes. *) let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in let* block = add block 1 "E" in - (* The new used storage is 232 + 39 (size of ticket) = 193. *) + (* The new used storage is 258 + 39 (size of ticket) = 297. *) let* () = - assert_used_contract_storage ~loc:__LOC__ block ticket_manager 271 + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 297 in - (* The paid storage also increases to 271. *) + (* The paid storage also increases to 297. *) let* () = - assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 271 + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 297 in (* There are now three rows in the ticket table: 3 x 66 = 198. *) let* () = assert_used_ticket_storage ~loc:__LOC__ block 198 in 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 8fe2cdd70f0222e698f45802da2078cc045a8d8b..f8984e995394d7a700cccc8437983a23281bd4ec 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 @@ -57,7 +57,7 @@ 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 tokens = (token, Script_int.to_zint amount) :: tokens in + let tokens = (token, Script_int.(to_zint (amount :> n num))) :: tokens in return (tokens, ctxt) in List.fold_left_es accum ([], ctxt) tickets @@ -65,12 +65,7 @@ let collect_token_amounts ctxt tickets = let tokens_of_value ~include_lazy ctxt ty x = let*? has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt ty in let* tickets, ctxt = - Ticket_scanner.tickets_of_value - ~include_lazy - ~allow_zero_amount_tickets:true - ctxt - has_tickets - x + Ticket_scanner.tickets_of_value ~include_lazy ctxt has_tickets x in let* tas, ctxt = collect_token_amounts ctxt tickets in let* bm, ctxt = @@ -290,6 +285,7 @@ module Ticket_manager = struct DUP 3 ; DUP 6 ; TICKET ; + ASSERT_SOME ; SOME ; DUP 5 ; GET_AND_UPDATE ; @@ -297,6 +293,7 @@ module Ticket_manager = struct DUP 3 ; DUP 6 ; TICKET ; + ASSERT_SOME ; SOME ; DUP 5 ; GET_AND_UPDATE ; @@ -304,6 +301,7 @@ module Ticket_manager = struct DIG 2 ; DIG 4 ; TICKET ; + ASSERT_SOME ; SOME ; DIG 3 ; GET_AND_UPDATE ; @@ -320,6 +318,7 @@ module Ticket_manager = struct DIG 3 ; DIG 3 ; TICKET ; + ASSERT_SOME ; CONS ; PAIR ; NIL operation ; @@ -330,6 +329,7 @@ module Ticket_manager = struct DUP 3 ; DUG 2 ; TICKET ; + ASSERT_SOME ; PUSH mutez 0 ; DIG 2 ; SOME ; @@ -346,6 +346,7 @@ module Ticket_manager = struct PUSH nat 99 ; PUSH string "NEW_TICKET_IN_ORIGINATED_CONTRACT" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 1 ; GET_AND_UPDATE ; @@ -408,6 +409,7 @@ module Ticket_manager = struct PUSH nat 1 ; PUSH string "ADDED_BY_REPLACE_BIG_MAP" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 11 ; GET_AND_UPDATE ; @@ -419,6 +421,7 @@ module Ticket_manager = struct PUSH nat 1 ; PUSH string "ADDED_BY_REPLACE_BIG_MAP" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 11 ; GET_AND_UPDATE ; @@ -479,6 +482,7 @@ module Ticket_manager = struct DIG 5 ; DIG 5 ; TICKET ; + ASSERT_SOME ; TRANSFER_TOKENS ; DUG 2 ; PAIR ; @@ -508,6 +512,7 @@ module Ticket_manager = struct PUSH nat 1 ; PUSH string "ADDED_BY_SEND_SELF_REPLACE" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 10 ; GET_AND_UPDATE ; @@ -528,6 +533,7 @@ module Ticket_manager = struct PUSH nat 1 ; PUSH string "ADDED_BY_SEND_SELF_REPLACE_TO_STORAGE" ; TICKET ; + ASSERT_SOME ; SOME ; PUSH int 11 ; GET_AND_UPDATE ; diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml index 14ffa19610bff34151ffda203209b027c036f6a0..25148e49afdc52849b4ea1a63296c8f1b51a4347 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml @@ -41,7 +41,7 @@ open Script_typed_ir type ticket_token_diff = { ticket_token : Ticket_token.ex_token; total_amount : Script_int.n Script_int.num; - destinations : (Destination.t * Script_int.n Script_int.num) list; + destinations : (Destination.t * ticket_amount) list; } let to_local_ticket_token_diff @@ -55,22 +55,25 @@ let wrap m = m >|= Environment.wrap_tzresult let assert_fails ~loc ?error m = let open Lwt_result_syntax in let*! res = m in + let rec aux err_res = + match (err_res, error) with + | Environment.Ecoproto_error err' :: rest, Some err -> + (* Matched exact error. *) + if err' = err then return_unit else aux rest + | _ :: rest, Some _ -> aux rest + | [], Some _ -> + (* Expected a different error. *) + let msg = + Printf.sprintf "Expected a different error at location %s" loc + in + Stdlib.failwith msg + | _, None -> + (* Any error is ok. *) + return () + in match res with | Ok _ -> Stdlib.failwith "Expected failure" - | Error err_res -> ( - match (err_res, error) with - | Environment.Ecoproto_error err' :: _, Some err when err = err' -> - (* Matched exact error. *) - return_unit - | _, Some _ -> - (* Expected a different error. *) - let msg = - Printf.sprintf "Expected a different error at location %s" loc - in - Stdlib.failwith msg - | _, None -> - (* Any error is ok. *) - return ()) + | Error err_res -> aux err_res let big_map_updates_of_key_values ctxt key_values = List.fold_right_es @@ -141,13 +144,13 @@ let string_of_destination_and_amounts cas = "[%a]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "; ") - (fun fmt (contract, amount) -> + (fun fmt (contract, (amount : ticket_amount)) -> Format.fprintf fmt {|("%a", %s)|} Destination.pp contract - (Script_int.to_string amount))) + Script_int.(to_string (amount :> n num)))) cas let string_of_ticket_operations_diff ctxt @@ -363,11 +366,10 @@ let transfer_operation_to_tx_rollup ~incr ~src ~parameters_ty ~parameters }, incr ) -let ticket_diffs_of_operations incr ~allow_zero_amount_tickets operations = +let ticket_diffs_of_operations incr operations = wrap @@ Ticket_operations_diff.ticket_diffs_of_operations (Incremental.alpha_ctxt incr) - ~allow_zero_amount_tickets operations let unit_script = @@ -397,7 +399,13 @@ let list_ticket_string_ty = let make_ticket (ticketer, contents, amount) = Script_string.of_string contents >>?= fun contents -> - return {ticketer; contents; amount = nat amount} + let amount = nat amount in + Option.value_e + ~error: + (Environment.Error_monad.trace_of_error + Script_tc_errors.Forbidden_zero_ticket_quantity) + @@ Ticket_amount.of_n amount + >>?= fun amount -> return {ticketer; contents; amount} let make_tickets ts = let* elements = List.map_es make_ticket ts in @@ -415,9 +423,7 @@ let test_non_ticket_operations () = let* _baker, src, block = init () in let* incr = Incremental.begin_construction block in let operations = [delegation_operation ~src] in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true operations - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr operations in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] (** Test transfer to a contract that does not take tickets. *) @@ -440,9 +446,7 @@ let test_transfer_to_non_ticket_contract () = ~parameters_ty:unit_t ~parameters:() in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] (** Test transfer an empty list of tickets. *) @@ -460,11 +464,17 @@ let test_transfer_empty_ticket_list () = let* operation, incr = transfer_tickets_operation ~incr ~src ~destination:orig_contract [] in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] +let one = Ticket_amount.one + +let two = Ticket_amount.add one one + +let three = Ticket_amount.add two one + +let five = Ticket_amount.add three two + (** Test transfer a list of one ticket. *) let test_transfer_one_ticket () = let* baker, src, block = init () in @@ -485,9 +495,7 @@ let test_transfer_one_ticket () = ~destination:orig_contract [(ticketer, "white", 1)] in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -498,7 +506,7 @@ let test_transfer_one_ticket () = ticket_token = string_token ~ticketer "white"; total_amount = nat 1; destinations = - [(Destination.Contract (Originated orig_contract), nat 1)]; + [(Destination.Contract (Originated orig_contract), one)]; }; ] @@ -530,36 +538,29 @@ let test_transfer_multiple_tickets () = ] in let orig_contract = Contract.Originated orig_contract in - let test allow_zero_amount_tickets = - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets [operation] - in - assert_equal_ticket_token_diffs - ctxt - ~loc:__LOC__ - ticket_diffs - ~expected: - [ - { - ticket_token = string_token ~ticketer "red"; - total_amount = nat 5; - destinations = [(Destination.Contract orig_contract, nat 5)]; - }; - { - ticket_token = string_token ~ticketer "blue"; - total_amount = nat 2; - destinations = [(Destination.Contract orig_contract, nat 2)]; - }; - { - ticket_token = string_token ~ticketer "green"; - total_amount = nat 3; - destinations = [(Destination.Contract orig_contract, nat 3)]; - }; - ] - in - (* Check for both value of the allow-zero-amount-tickets flag. *) - let* () = test true in - test false + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 5; + destinations = [(Destination.Contract orig_contract, five)]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 3; + destinations = [(Destination.Contract orig_contract, three)]; + }; + ] (** Test transfer a list of tickets of different types. *) let test_transfer_different_tickets () = @@ -592,9 +593,7 @@ let test_transfer_different_tickets () = ] in let destination = Destination.Contract (Originated destination) in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -604,32 +603,32 @@ let test_transfer_different_tickets () = { ticket_token = string_token ~ticketer:ticketer1 "red"; total_amount = nat 2; - destinations = [(destination, nat 2)]; + destinations = [(destination, two)]; }; { ticket_token = string_token ~ticketer:ticketer1 "green"; total_amount = nat 2; - destinations = [(destination, nat 2)]; + destinations = [(destination, two)]; }; { ticket_token = string_token ~ticketer:ticketer1 "blue"; total_amount = nat 2; - destinations = [(destination, nat 2)]; + destinations = [(destination, two)]; }; { ticket_token = string_token ~ticketer:ticketer2 "red"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; { ticket_token = string_token ~ticketer:ticketer2 "green"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; { ticket_token = string_token ~ticketer:ticketer2 "blue"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; ] @@ -666,11 +665,9 @@ let test_transfer_to_two_contracts_with_different_tickets () = transfer_tickets_operation ~incr ~src ~destination:destination2 parameters in let* ticket_diffs, ctxt = - ticket_diffs_of_operations - incr - ~allow_zero_amount_tickets:true - [operation1; operation2] + ticket_diffs_of_operations incr [operation1; operation2] in + let one = Ticket_amount.one in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -682,8 +679,8 @@ let test_transfer_to_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract (Originated destination1), nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); ]; }; { @@ -691,8 +688,8 @@ let test_transfer_to_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract (Originated destination1), nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); ]; }; { @@ -700,8 +697,8 @@ let test_transfer_to_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract (Originated destination1), nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); ]; }; ] @@ -718,9 +715,7 @@ let test_originate_non_ticket_contract () = ~storage:"Unit" ~forges_tickets:false in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] (** Test originate a contract with an empty list of tickets. *) @@ -736,9 +731,7 @@ let test_originate_with_empty_tickets_list () = ~storage ~forges_tickets:false in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] (** Test originate a contract with a single ticket. *) @@ -757,9 +750,7 @@ let test_originate_with_one_ticket () = ~storage ~forges_tickets:true in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -769,7 +760,7 @@ let test_originate_with_one_ticket () = { ticket_token = string_token ~ticketer "white"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; ] @@ -800,9 +791,7 @@ let test_originate_with_multiple_tickets () = ~storage ~forges_tickets:true in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -812,17 +801,17 @@ let test_originate_with_multiple_tickets () = { ticket_token = string_token ~ticketer "red"; total_amount = nat 5; - destinations = [(Destination.Contract orig_contract, nat 5)]; + destinations = [(Destination.Contract orig_contract, five)]; }; { ticket_token = string_token ~ticketer "blue"; total_amount = nat 2; - destinations = [(Destination.Contract orig_contract, nat 2)]; + destinations = [(Destination.Contract orig_contract, two)]; }; { ticket_token = string_token ~ticketer "green"; total_amount = nat 3; - destinations = [(Destination.Contract orig_contract, nat 3)]; + destinations = [(Destination.Contract orig_contract, three)]; }; ] @@ -864,9 +853,7 @@ let test_originate_with_different_tickets () = ~storage ~forges_tickets:true in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -876,32 +863,32 @@ let test_originate_with_different_tickets () = { ticket_token = string_token ~ticketer:ticketer1 "red"; total_amount = nat 2; - destinations = [(Destination.Contract orig_contract, nat 2)]; + destinations = [(Destination.Contract orig_contract, two)]; }; { ticket_token = string_token ~ticketer:ticketer1 "green"; total_amount = nat 2; - destinations = [(Destination.Contract orig_contract, nat 2)]; + destinations = [(Destination.Contract orig_contract, two)]; }; { ticket_token = string_token ~ticketer:ticketer1 "blue"; total_amount = nat 2; - destinations = [(Destination.Contract orig_contract, nat 2)]; + destinations = [(Destination.Contract orig_contract, two)]; }; { ticket_token = string_token ~ticketer:ticketer2 "red"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; { ticket_token = string_token ~ticketer:ticketer2 "green"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; { ticket_token = string_token ~ticketer:ticketer2 "blue"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; ] @@ -937,10 +924,7 @@ let test_originate_two_contracts_with_different_tickets () = ~forges_tickets:true in let* ticket_diffs, ctxt = - ticket_diffs_of_operations - incr - ~allow_zero_amount_tickets:true - [operation1; operations2] + ticket_diffs_of_operations incr [operation1; operations2] in assert_equal_ticket_token_diffs ctxt @@ -953,8 +937,8 @@ let test_originate_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract orig_contract2, nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); ]; }; { @@ -962,8 +946,8 @@ let test_originate_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract orig_contract2, nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); ]; }; { @@ -971,8 +955,8 @@ let test_originate_two_contracts_with_different_tickets () = total_amount = nat 2; destinations = [ - (Destination.Contract orig_contract2, nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); ]; }; ] @@ -1016,10 +1000,7 @@ let test_originate_and_transfer () = [(ticketer, "red", 1); (ticketer, "green", 1); (ticketer, "blue", 1)] in let* ticket_diffs, ctxt = - ticket_diffs_of_operations - incr - ~allow_zero_amount_tickets:true - [operation1; operation2] + ticket_diffs_of_operations incr [operation1; operation2] in assert_equal_ticket_token_diffs ctxt @@ -1032,8 +1013,8 @@ let test_originate_and_transfer () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); ]; }; { @@ -1041,8 +1022,8 @@ let test_originate_and_transfer () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); ]; }; { @@ -1050,8 +1031,8 @@ let test_originate_and_transfer () = total_amount = nat 2; destinations = [ - (Destination.Contract (Originated destination2), nat 1); - (Destination.Contract orig_contract1, nat 1); + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); ]; }; ] @@ -1090,9 +1071,7 @@ let test_originate_big_map_with_tickets () = ~storage ~forges_tickets:true in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -1102,17 +1081,17 @@ let test_originate_big_map_with_tickets () = { ticket_token = string_token ~ticketer "red"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; { ticket_token = string_token ~ticketer "green"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; { ticket_token = string_token ~ticketer "blue"; total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; + destinations = [(Destination.Contract orig_contract, one)]; }; ] @@ -1172,9 +1151,7 @@ let test_transfer_big_map_with_tickets () = ~parameters_ty ~parameters in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in let destination = Destination.Contract (Originated orig_contract) in assert_equal_ticket_token_diffs ctxt @@ -1185,17 +1162,17 @@ let test_transfer_big_map_with_tickets () = { ticket_token = string_token ~ticketer:ticketer_contract "red"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; { ticket_token = string_token ~ticketer:ticketer_contract "green"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; { ticket_token = string_token ~ticketer:ticketer_contract "blue"; total_amount = nat 1; - destinations = [(destination, nat 1)]; + destinations = [(destination, one)]; }; ] @@ -1219,9 +1196,7 @@ let test_tx_rollup_deposit_one_ticket () = pair_t Micheline.dummy_location ticket_ty tx_rollup_l2_address_t) |> Environment.wrap_tzresult in - let amount = - Script_int.(is_nat @@ of_int 1) |> WithExceptions.Option.get ~loc:__LOC__ - in + let amount = one in let*? contents = Script_string.of_string "white" |> Environment.wrap_tzresult in @@ -1242,9 +1217,7 @@ let test_tx_rollup_deposit_one_ticket () = ~parameters_ty ~parameters in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in + let* ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ @@ -1254,13 +1227,13 @@ let test_tx_rollup_deposit_one_ticket () = { ticket_token = string_token ~ticketer "white"; total_amount = nat 1; - destinations = [(Destination.Tx_rollup tx_rollup, nat 1)]; + destinations = [(Destination.Tx_rollup tx_rollup, one)]; }; ] (** Test transferring a list of multiple tickets where two of them have zero - amounts. This should work when zero-tickets are enabled. *) -let test_transfer_multiple_zero_tickets () = + amounts fails. *) +let test_transfer_fails_on_multiple_zero_tickets () = let* baker, src, block = init () in let* ticketer = one_ticketer block in let* orig_contract, incr = @@ -1272,48 +1245,23 @@ let test_transfer_multiple_zero_tickets () = ~storage:"{}" ~forges_tickets:false in - let* operation, incr = - transfer_tickets_operation - ~incr - ~src - ~destination:orig_contract - [ - (ticketer, "red", 1); - (ticketer, "blue", 0); - (ticketer, "green", 2); - (ticketer, "red", 0); - (ticketer, "green", 3); - ] - in - let* ticket_diffs, ctxt = - ticket_diffs_of_operations incr ~allow_zero_amount_tickets:true [operation] - in - let orig_contract = Contract.Originated orig_contract in - assert_equal_ticket_token_diffs - ctxt + assert_fails ~loc:__LOC__ - ticket_diffs - ~expected: - [ - { - ticket_token = string_token ~ticketer "blue"; - total_amount = nat 0; - destinations = [(Destination.Contract orig_contract, nat 0)]; - }; - { - ticket_token = string_token ~ticketer "red"; - total_amount = nat 1; - destinations = [(Destination.Contract orig_contract, nat 1)]; - }; - { - ticket_token = string_token ~ticketer "green"; - total_amount = nat 5; - destinations = [(Destination.Contract orig_contract, nat 5)]; - }; - ] + ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ (* let* operation, incr = *) + transfer_tickets_operation + ~incr + ~src + ~destination:orig_contract + [ + (ticketer, "red", 1); + (ticketer, "blue", 0); + (ticketer, "green", 2); + (ticketer, "red", 0); + (ticketer, "green", 3); + ] -(** Test that zero-amount tickets are detected and that an error is yielded - when the [allow_zero_amount_tickets] flag is set to [false]. *) +(** Test that zero-amount tickets are detected and that an error is yielded. *) let test_fail_on_zero_amount_tickets () = let* baker, src, block = init () in let* ticketer = one_ticketer block in @@ -1333,22 +1281,16 @@ let test_fail_on_zero_amount_tickets () = ticketer_addr ticketer_addr in - let* _orig_contract, operation, ctxt = - origination_operation - block - ~src - ~baker - ~script:ticket_list_script - ~storage - ~forges_tickets:true - in assert_fails ~loc:__LOC__ - ~error:Ticket_scanner.Forbidden_zero_ticket_quantity - (ticket_diffs_of_operations - ctxt - ~allow_zero_amount_tickets:false - [operation]) + ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ origination_operation + block + ~src + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true let tests = [ @@ -1418,9 +1360,9 @@ let tests = `Quick test_tx_rollup_deposit_one_ticket; Tztest.tztest - "Test transfer multiple zero tickets" + "Test transfer fails on multiple zero tickets" `Quick - test_transfer_multiple_zero_tickets; + test_transfer_fails_on_multiple_zero_tickets; Tztest.tztest "Test fail in zero-amount tickets" `Quick diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_scanner.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_scanner.ml index 7ecfe356d03b15fe4764963813aead5ffb9e80f3..c8dfe4b987ced12c778be41903c868aebf38c7cb 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_scanner.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_ticket_scanner.ml @@ -39,22 +39,23 @@ open Alpha_context let assert_fails ~loc ?error m = let open Lwt_result_syntax in let*! res = m in + let rec aux err_res = + match (err_res, error) with + | Environment.Ecoproto_error err' :: rest, Some err -> + if err = err' then return_unit else aux rest + | _, Some _ -> + (* Expected a different error. *) + let msg = + Printf.sprintf "Expected a different error at location %s" loc + in + Stdlib.failwith msg + | _, None -> + (* Any error is ok. *) + return () + in match res with | Ok _ -> Stdlib.failwith "Expected failure" - | Error err_res -> ( - match (err_res, error) with - | Environment.Ecoproto_error err' :: _, Some err when err = err' -> - (* Matched exact error. *) - return_unit - | _, Some _ -> - (* Expected a different error. *) - let msg = - Printf.sprintf "Expected a different error at location %s" loc - in - Stdlib.failwith msg - | _, None -> - (* Any error is ok. *) - return ()) + | Error err_res -> aux err_res let ( let* ) m f = m >>=? f @@ -95,7 +96,7 @@ let string_list_of_ex_tickets ctxt tickets = ticketer content Z.pp_print - (Script_int.to_zint amount) + Script_int.(to_zint (amount :> n num)) in return (str :: xs, ctxt) in @@ -113,6 +114,9 @@ let make_ex_ticket ctxt ~ticketer ~type_exp ~content_exp ~amount = wrap @@ Script_ir_translator.parse_comparable_data ctxt cty node in let amount = Script_int.(abs @@ of_int amount) in + let amount = + WithExceptions.Option.get ~loc:__LOC__ @@ Ticket_amount.of_n amount + in let ticket = Script_typed_ir.{ticketer; contents; amount} in return (Ticket_scanner.Ex_ticket (cty, ticket), ctxt) @@ -125,8 +129,7 @@ let assert_equals_ex_tickets ctxt ~loc ex_tickets expected = (List.sort String.compare str_tickets) (List.sort String.compare str_tickets_expected) -let tickets_of_value ctxt ~include_lazy ~allow_zero_amount_tickets ~type_exp - ~value_exp = +let tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp = let Script_typed_ir.Ex_ty ty, ctxt = let node = Micheline.root @@ Expr.from_string type_exp in Result.value_f @@ -146,35 +149,17 @@ let tickets_of_value ctxt ~include_lazy ~allow_zero_amount_tickets ~type_exp let* ht, ctxt = wrap @@ Lwt.return @@ Ticket_scanner.type_has_tickets ctxt ty in - wrap - @@ Ticket_scanner.tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets - ht - value - -let assert_contains_tickets ctxt ~loc ~include_lazy ~allow_zero_amount_tickets - ~type_exp ~value_exp expected = + wrap @@ Ticket_scanner.tickets_of_value ctxt ~include_lazy ht value + +let assert_contains_tickets ctxt ~loc ~include_lazy ~type_exp ~value_exp + expected = let* ex_tickets, _ = - tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets - ~type_exp - ~value_exp + tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp in assert_equals_ex_tickets ctxt ~loc ex_tickets expected -let assert_fail_non_empty_overlay ctxt ~loc ~include_lazy - ~allow_zero_amount_tickets ~type_exp ~value_exp = - tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets - ~type_exp - ~value_exp - >>= fun res -> +let assert_fail_non_empty_overlay ctxt ~loc ~include_lazy ~type_exp ~value_exp = + tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp >>= fun res -> match res with | Error [x] -> let x = Format.kasprintf Fun.id "%a" Error_monad.pp x in @@ -263,7 +248,6 @@ let assert_big_map_int_ticket_string_ref ~loc ~pre_populated ~big_map_exp assert_contains_tickets ctxt ~include_lazy:true - ~allow_zero_amount_tickets:true ~loc ~type_exp:"big_map int (ticket string)" ~value_exp @@ -275,7 +259,6 @@ let assert_fail_non_empty_overlay_with_big_map_ref ~loc ~pre_populated assert_fail_non_empty_overlay ctxt ~include_lazy:true - ~allow_zero_amount_tickets:true ~loc ~type_exp:"big_map int (ticket string)" ~value_exp @@ -283,40 +266,22 @@ let assert_fail_non_empty_overlay_with_big_map_ref ~loc ~pre_populated let assert_string_tickets ~loc ~include_lazy ~type_exp ~value_exp ~expected = let* ctxt = new_ctxt () in let* ex_tickets, ctxt = make_string_tickets ctxt expected in - let contains_zero_amount_tickets = - List.exists (fun (_, _, amount) -> amount = 0) expected - in let* () = assert_contains_tickets ctxt ~include_lazy - ~allow_zero_amount_tickets:true ~loc ~type_exp ~value_exp ex_tickets in - if contains_zero_amount_tickets then - assert_fails - ~loc:__LOC__ - ~error:Ticket_scanner.Forbidden_zero_ticket_quantity - (tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets:false - ~type_exp - ~value_exp) - else - (* If there are no zero-amount tickets we still want them to pass with - [allow_zero_amount_tickets] flag set to false. *) - assert_contains_tickets - ctxt - ~include_lazy - ~allow_zero_amount_tickets:false - ~loc - ~type_exp - ~value_exp - ex_tickets + assert_contains_tickets + ctxt + ~include_lazy + ~loc + ~type_exp + ~value_exp + ex_tickets (** Test that the ticket can be extracted from a a single unit ticket *) let test_tickets_in_unit_ticket () = @@ -335,11 +300,31 @@ let test_tickets_in_unit_ticket () = ctxt ~loc:__LOC__ ~include_lazy:false - ~allow_zero_amount_tickets:true ~type_exp ~value_exp [ex_ticket] +let assert_string_tickets_fail_on_zero_amount ~loc ~include_lazy ~type_exp + ~value_exp = + let* ctxt = new_ctxt () in + assert_fails ~loc ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp + +let test_tickets_in_list_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"list(ticket(string))" + ~value_exp: + {| + { + Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; + Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2; + Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3; + Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "orange" 0; + } + |} + (** Test that all tickets can be extracted from a list of tickets *) let test_tickets_in_list () = assert_string_tickets @@ -352,7 +337,6 @@ let test_tickets_in_list () = Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2; Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3; - Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "orange" 0; } |} ~expected: @@ -360,29 +344,53 @@ let test_tickets_in_list () = ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 3); - ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "orange", 0); ] +let test_tickets_in_pair_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"pair (ticket string) (ticket string) (ticket string)" + ~value_exp: + {| + Pair + (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1) + (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2) + (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 0) + |} + (** Test that all tickets can be extracted from a pair of tickets *) let test_tickets_in_pair () = assert_string_tickets ~loc:__LOC__ ~include_lazy:false - ~type_exp:"pair (ticket string) (ticket string) (ticket string)" + ~type_exp:"pair (ticket string) (ticket string)" ~value_exp: {| Pair (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1) (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2) - (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 0) |} ~expected: [ ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); - ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 0); ] +let test_tickets_in_map_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"map int (ticket string)" + ~value_exp: + {| + { + Elt 1 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1); + Elt 2 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2); + Elt 3 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 0); + } + |} + (** Test that all tickets from a map can be extracted. *) let test_tickets_in_map () = assert_string_tickets @@ -394,14 +402,12 @@ let test_tickets_in_map () = { Elt 1 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1); Elt 2 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2); - Elt 3 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 0); } |} ~expected: [ ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); - ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 0); ] (** Test that all tickets from a big-map with non-empty overlay fails. @@ -414,7 +420,6 @@ let test_tickets_in_big_map () = ctxt ~loc:__LOC__ ~include_lazy:true - ~allow_zero_amount_tickets:false ~type_exp:"big_map int (ticket string)" ~value_exp: {| @@ -436,7 +441,7 @@ let test_tickets_in_big_map_strict_only () = { Elt 1 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1); Elt 2 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2); - Elt 3 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 0); + Elt 3 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3); } |} ~expected:[] @@ -451,7 +456,6 @@ let test_tickets_in_list_in_big_map () = ctxt ~loc:__LOC__ ~include_lazy:true - ~allow_zero_amount_tickets:true ~type_exp:"(big_map int (list(ticket string)))" ~value_exp: {| @@ -501,15 +505,14 @@ let test_tickets_in_or_left () = ~value_exp:{| Left (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1) |} ~expected:[("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1)] -(** Test that tickets can be extracted from the left side of an or-expression - with zero-amount ticket. *) +(** Test that tickets from the left side of an or-expression with zero amount + are rejected. *) let test_tickets_in_or_left_with_zero_amount () = - assert_string_tickets + assert_string_tickets_fail_on_zero_amount ~loc:__LOC__ ~include_lazy:false ~type_exp:"or (ticket string) int" ~value_exp:{| Left (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 0) |} - ~expected:[("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 0)] (** Test that tickets can be extracted from the right side of an or-expression. *) let test_tickets_in_or_right () = @@ -635,8 +638,20 @@ let tests = `Quick test_tickets_in_unit_ticket; Tztest.tztest "Test tickets in list" `Quick test_tickets_in_list; + Tztest.tztest + "Test tickets in list with zero amount" + `Quick + test_tickets_in_list_with_zero_amount; Tztest.tztest "Test tickets in pair" `Quick test_tickets_in_pair; + Tztest.tztest + "Test tickets in pair with zero amount" + `Quick + test_tickets_in_pair_with_zero_amount; Tztest.tztest "Test tickets in map" `Quick test_tickets_in_map; + Tztest.tztest + "Test tickets in map with zero amount" + `Quick + test_tickets_in_map_with_zero_amount; Tztest.tztest "Test tickets in big map" `Quick test_tickets_in_big_map; Tztest.tztest "Test tickets in big map with include lazy set to false" @@ -653,7 +668,7 @@ let tests = test_tickets_in_pair_big_map_and_list_strict_only; Tztest.tztest "Test tickets in or left" `Quick test_tickets_in_or_left; Tztest.tztest - "Test tickets in or left" + "Test tickets in or left with zero amount" `Quick test_tickets_in_or_left_with_zero_amount; Tztest.tztest "Test tickets in or right" `Quick test_tickets_in_or_right; diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit.tz b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit.tz index c016f9bf9c4ec61d0296f8213f37658f39a6911c..e07e83aa71953cd5486aa8754c6ba9e08bb4aba9 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit.tz +++ b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit.tz @@ -17,6 +17,7 @@ code { PUSH nat 100000; PUSH unit Unit; TICKET; + ASSERT_SOME; PAIR ; diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_incorrect_entrypoint.tz b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_incorrect_entrypoint.tz index 3ad04d1bc0183a01d0a4f85dfa9ed363e972a4d7..f029a2583085b2cb42573ec5cabe4f643f9f1d17 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_incorrect_entrypoint.tz +++ b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_incorrect_entrypoint.tz @@ -17,6 +17,7 @@ code { PUSH nat 10; PUSH unit Unit; TICKET; + ASSERT_SOME; PAIR ; diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_one_mutez.tz b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_one_mutez.tz index 58eb3095cdeab1616887a78946b8a769c50c4b19..82aa389266a5bf402acc61f7af0830a6d3232bda 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_one_mutez.tz +++ b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_one_mutez.tz @@ -17,6 +17,7 @@ code { PUSH nat 10; PUSH unit Unit; TICKET; + ASSERT_SOME; PAIR ; diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_pair_string.tz b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_pair_string.tz index de50754c46d74f03585735b5ac59a834a92fe4fe..d554c713f05600e577ba05bbcfef6c34ab584e92 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_pair_string.tz +++ b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_pair_string.tz @@ -16,6 +16,7 @@ code { UNIT; PAIR; TICKET; + ASSERT_SOME; PAIR; # amount for transfering diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_string.tz b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_string.tz index af81b322b564c7b5936be306b9817965ba8d8d70..977698a30239f180ee5d3ac536480c2751bab4e7 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_string.tz +++ b/src/proto_alpha/lib_protocol/test/integration/operations/contracts/tx_rollup_deposit_string.tz @@ -14,6 +14,7 @@ code { PUSH nat 10; SWAP; TICKET; + ASSERT_SOME; PAIR; # amount for transfering diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml index 61cb20be242cd4dc64f03e21eccbb23653fdcfcb..b8e8024ba86133e186c391e8f9a8e5fac6b7855e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml @@ -1185,15 +1185,28 @@ let test_zero_amount_ticket () = ] in let output = make_output ~outbox_level:0 ~message_index:0 transactions in - assert_fails - ~loc:__LOC__ - ~error:Ticket_scanner.Forbidden_zero_ticket_quantity - (execute_outbox_message_without_proof_validation - incr - rollup - ~cemented_commitment - ~source - output) + let*! result = + execute_outbox_message_without_proof_validation + incr + rollup + ~cemented_commitment + ~source + output + in + match result with + | Error e -> + if + Option.is_some + @@ List.find + (function + | Environment.Ecoproto_error + Script_tc_errors.Forbidden_zero_ticket_quantity -> + true + | _ -> false) + e + then return_unit + else Stdlib.failwith "Expected failure" + | Ok _ -> Stdlib.failwith "Expected failure" (* Check that executing an outbox message fails when the inclusion proof in invalid. *) diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml index c3e004e07b53a4aa1f4c16557611f1f3d0ab8448..18965a83f8bdd24ba9040e701bb20161b9fb79e4 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml @@ -110,6 +110,7 @@ let contract_originate block account = PUSH nat 0; PUSH string "ticket payload"; TICKET; + ASSERT_SOME; TRANSFER_TOKENS; } { IF_LEFT { @@ -118,6 +119,7 @@ let contract_originate block account = PUSH nat 137; PUSH string "G"; TICKET; + ASSERT_SOME; TRANSFER_TOKENS; } { NEVER @@ -334,9 +336,12 @@ let test_transfer_zero_amount_ticket () = ~param ~entrypoint:"transfer_zero_ticket" ~expect_apply_failure: - (check_proto_error ~loc:__LOC__ ~exp:"Forbidden_zero_ticket_quantity" - @@ function - | [Ticket_scanner.Forbidden_zero_ticket_quantity] -> return_unit + (check_proto_error ~loc:__LOC__ ~exp:"Script_rejected" @@ function + | [ + Script_interpreter.Runtime_contract_error _; + Script_interpreter.Reject _; + ] -> + return_unit | _ -> raise Unexpected_error) in return_unit 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 60876263147f4c4391e94a902e0f04d2ac2d1389..e572e29800953a07c5b338ee3f908b306cbfde85 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 @@ -548,6 +548,7 @@ module Nat_ticket = struct PUSH nat %a; PUSH %s %d; TICKET; + ASSERT_SOME; PAIR ; TRANSFER_TOKENS; PUSH unit Unit; @@ -4082,6 +4083,7 @@ module Withdraw = struct { UNPAIR; TICKET; + ASSERT_SOME; CONS; NIL operation; PAIR @@ -4358,9 +4360,12 @@ module Withdraw = struct ~contents:(Script.lazy_expr Nat_ticket.contents) ~ty:(Script.lazy_expr Nat_ticket.ty) ~ticketer:deposit_contract - (Tx_rollup_l2_qty.to_z half_amount) + ~amount: + (WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_z + @@ Script_int.of_int64 int64_half_amount) ~destination:withdraw_contract - entrypoint + ~entrypoint >>=? fun operation -> Block.bake ~operation block >>=? fun block -> (* 4.1 We assert that [withdraw_contract] has received the ticket as @@ -4430,9 +4435,12 @@ module Withdraw = struct ~contents:(Script.lazy_expr Nat_ticket.contents) ~ty:(Script.lazy_expr Nat_ticket.ty) ~ticketer:deposit_contract - (Tx_rollup_l2_qty.to_z half_amount) + ~amount: + (WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_z + @@ Script_int.of_int64 int64_half_amount) ~destination:withdraw_dropping_contract - entrypoint + ~entrypoint >>=? fun operation -> Block.bake ~operation block >>=? fun block -> (* 4. Finally, we assert that [withdraw_contract] has received the ticket as @@ -4842,18 +4850,18 @@ module Withdraw = struct ~contents:(Script.lazy_expr Nat_ticket.contents) ~ty:(Script.lazy_expr Nat_ticket.ty) ~ticketer:deposit_contract - qty + ~amount:qty ~destination:withdraw_contract - Entrypoint.default + ~entrypoint:Entrypoint.default in (* Execute withdraw with half amount *) - withdraw_op account1 block Z.one >>=? fun operation -> + withdraw_op account1 block Ticket_amount.one >>=? fun operation -> Block.bake ~operation block >>=? fun block -> (* Execute withdraw with the rest amount *) - withdraw_op account1 block Z.one >>=? fun operation -> + withdraw_op account1 block Ticket_amount.one >>=? fun operation -> Block.bake ~operation block >>=? fun block -> (* Execute again, now should fail with a ticket table error *) - withdraw_op account1 block Z.one >>=? fun operation -> + withdraw_op account1 block Ticket_amount.one >>=? fun operation -> Incremental.begin_construction block >>=? fun incr -> Incremental.add_operation ~expect_apply_failure:(function @@ -4880,8 +4888,10 @@ module Withdraw = struct [ticket_info3; ticket_info4] >>=? fun operation -> Block.bake ~operation block >>=? fun block -> - withdraw_op account1 block (Z.of_int 2) >>=? fun operation1 -> - withdraw_op account2 block (Z.of_int 2) >>=? fun operation2 -> + withdraw_op account1 block Ticket_amount.(add one one) + >>=? fun operation1 -> + withdraw_op account2 block Ticket_amount.(add one one) + >>=? fun operation2 -> Block.bake ~operations:[operation1; operation2] block >>=? fun _block -> return_unit @@ -5460,9 +5470,12 @@ module Withdraw = struct ~contents:(Script.lazy_expr Nat_ticket.contents) ~ty:(Script.lazy_expr Nat_ticket.ty) ~ticketer:forge_withdraw_deposit_contract - (Tx_rollup_l2_qty.to_z Nat_ticket.amount) + ~amount: + (WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_zint + @@ Tx_rollup_l2_qty.to_z Nat_ticket.amount) ~destination:forge_withdraw_deposit_contract - (Entrypoint.of_string_strict_exn "withdraw") + ~entrypoint:(Entrypoint.of_string_strict_exn "withdraw") >>=? fun operation -> Block.bake ~operation block in let token_one = @@ -5523,173 +5536,6 @@ module Withdraw = struct assert_tx_rollup_ticket_balance ~__LOC__ block (Some 10) >>=? fun () -> assert_account_ticket_balance ~__LOC__ block None - let test_0_amount_tickets () = - context_init1 () >>=? fun (block, account) -> - originate block account >>=? fun (block, tx_rollup) -> - originate_forge_withdraw_deposit_contract account block - >>=? fun (forge_withdraw_deposit_contract, block) -> - let forge_ticket block = - Op.transaction - (B block) - ~entrypoint:Entrypoint.default - ~parameters: - (Expr_common.( - pair_n [int (Z.of_int Nat_ticket.contents_nat); int Z.zero]) - |> Tezos_micheline.Micheline.strip_locations |> Script.lazy_expr) - ~fee:Tez.one - account - forge_withdraw_deposit_contract - (Tez.of_mutez_exn 0L) - >>=? fun operation -> Block.bake ~operation block - in - let failing_deposit_ticket block = - Op.transaction - (B block) - ~entrypoint:(Entrypoint.of_string_strict_exn "deposit") - ~parameters: - (Expr_common.( - pair_n - [ - string (Tx_rollup.to_b58check tx_rollup); - string "tz4MSfZsn6kMDczShy8PMeB628TNukn9hi2K"; - ]) - |> Tezos_micheline.Micheline.strip_locations |> Script.lazy_expr) - ~fee:Tez.one - account - forge_withdraw_deposit_contract - (Tez.of_mutez_exn 0L) - >>=? fun operation -> - Incremental.begin_construction block >>=? fun incr -> - Incremental.add_operation - ~expect_apply_failure: - (check_proto_error Ticket_scanner.Forbidden_zero_ticket_quantity) - incr - operation - >>=? fun _incr -> return_unit - in - let failing_dispatch_ticket block = - Nat_ticket.withdrawal - ~amount:Tx_rollup_l2_qty.zero - (B block) - ~ticketer:forge_withdraw_deposit_contract - ~claimer:account - tx_rollup - >>=? fun (withdraw, ticket_info) -> - let message_index = 0 in - finalize_all_commitment_with_withdrawals - ~batches:["batch"] - ~account - ~tx_rollup - ~withdrawals:[(message_index, [withdraw])] - block - >>=? fun (commitment, context_hash_list, committed_level, block) -> - let context_hash = - WithExceptions.Option.get - ~loc:__LOC__ - (List.nth context_hash_list message_index) - in - let message_result_path = - compute_message_result_path commitment ~message_position:message_index - in - Op.tx_rollup_dispatch_tickets - (B block) - ~source:account - ~message_index - ~message_result_path - tx_rollup - committed_level - context_hash - [ticket_info] - >>=? fun operation -> - Incremental.begin_construction block >>=? fun incr -> - Incremental.add_operation - ~expect_apply_failure: - (check_proto_error Ticket_scanner.Forbidden_zero_ticket_quantity) - incr - operation - >>=? fun _incr -> return_unit - in - let failing_transfer_ticket block = - Op.transfer_ticket - (B block) - ~source:account - ~contents:(Script.lazy_expr Nat_ticket.contents) - ~ty:(Script.lazy_expr Nat_ticket.ty) - ~ticketer:forge_withdraw_deposit_contract - Z.zero - ~destination:forge_withdraw_deposit_contract - (Entrypoint.of_string_strict_exn "withdraw") - >>=? fun operation -> - Incremental.begin_construction block >>=? fun incr -> - Incremental.add_operation - ~expect_apply_failure: - (check_proto_error Ticket_scanner.Forbidden_zero_ticket_quantity) - incr - operation - >>=? fun _incr -> return_unit - in - let token_one = - Nat_ticket.ex_token ~ticketer:forge_withdraw_deposit_contract - in - let assert_ticket_in_storage block = - let expected_storage = - Expr_common.( - seq - [ - pair - (address forge_withdraw_deposit_contract) - (pair (int (Z.of_int Nat_ticket.contents_nat)) (int Z.zero)); - ]) - |> Tezos_micheline.Micheline.strip_locations |> Option.some - in - Incremental.begin_construction block >>=? fun incr -> - let ctxt = Incremental.alpha_ctxt incr in - Contract.get_storage ctxt forge_withdraw_deposit_contract - >>=?? fun (_ctxt, found_storage) -> - if expected_storage = found_storage then return_unit - else - Alcotest.fail - (Format.sprintf - "Found storage: %s@,expected storage: %s@," - (match found_storage with - | Some s -> Expr.to_string s - | None -> "None") - (match expected_storage with - | Some s -> Expr.to_string s - | None -> "None")) - in - let assert_contract_ticket_balance ~__LOC__ block balance = - assert_ticket_balance - ~loc:__LOC__ - block - token_one - (Contract forge_withdraw_deposit_contract) - balance - in - let assert_account_ticket_balance ~__LOC__ block balance = - assert_ticket_balance - ~loc:__LOC__ - block - token_one - (Contract account) - balance - in - let assert_tx_rollup_ticket_balance ~__LOC__ block balance = - assert_ticket_balance - ~loc:__LOC__ - block - token_one - (Tx_rollup tx_rollup) - balance - in - forge_ticket block >>=? fun block -> - assert_ticket_in_storage block >>=? fun () -> - assert_contract_ticket_balance ~__LOC__ block None >>=? fun () -> - assert_tx_rollup_ticket_balance ~__LOC__ block None >>=? fun () -> - assert_account_ticket_balance ~__LOC__ block None >>=? fun () -> - failing_deposit_ticket block >>=? fun () -> - failing_dispatch_ticket block >>=? fun () -> failing_transfer_ticket block - let tests = [ Tztest.tztest "Test withdraw" `Quick test_valid_withdraw; @@ -5736,10 +5582,6 @@ module Withdraw = struct batches" `Quick test_forge_deposit_withdraw_deposit; - Tztest.tztest - "Test to deposit/dispatch/transfer 0 tickets" - `Quick - test_0_amount_tickets; ] end diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml index c1bd639da1e3ba7cb969f4599999ad125ac746d0..c6e0d8fa4ad8f9e04b223b17f062131fe20719cd 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -842,13 +842,13 @@ let mk_transfer_ticket (oinfos : operation_req) (infos : infos) = (match infos.accounts.tx with | None -> infos.accounts.source | Some tx -> tx)) - Z.zero + ~amount:Ticket_amount.one ~destination: (contract_of (match infos.accounts.dest with | None -> infos.accounts.source | Some dest -> dest)) - Entrypoint.default + ~entrypoint:Entrypoint.default let mk_tx_rollup_dispacth_ticket (oinfos : operation_req) (infos : infos) = let open Lwt_result_syntax in diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml index 186f88bb2f884b49ba14994a0a7dcb263eae0fdc..86ae64837a9040407a52917ec0f1596f92c6e5ab 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml @@ -72,7 +72,10 @@ let check_encode_decode_outbox_message ctxt message = let string_ticket ticketer contents amount = let open WithExceptions in - let amount = Script_int.abs @@ Script_int.of_int amount in + let amount = + Option.get ~loc:__LOC__ @@ Ticket_amount.of_n @@ Script_int.abs + @@ Script_int.of_int amount + in let ticketer = Result.get_ok ~loc:__LOC__ (Contract.of_b58check ticketer) in let contents = Result.get_ok ~loc:__LOC__ (Script_string.of_string contents) @@ -202,7 +205,7 @@ let add_or_clear = storage (list (ticket string)) ; code { UNPAIR ; IF_LEFT - { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; CONS ; NIL operation ; PAIR } + { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; ASSERT_SOME ; CONS ; NIL operation ; PAIR } { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } |} diff --git a/src/proto_alpha/lib_protocol/ticket_accounting.ml b/src/proto_alpha/lib_protocol/ticket_accounting.ml index 64c2273f18fd5dde2c9a2fde9d31ed2126e75f41..bbb04f408bfa389d30a085003f9eb2f01c3a84f1 100644 --- a/src/proto_alpha/lib_protocol/ticket_accounting.ml +++ b/src/proto_alpha/lib_protocol/ticket_accounting.ml @@ -74,18 +74,16 @@ module Ticket_token_map = struct end let ticket_balances_of_value ctxt ~include_lazy ty value = - Ticket_scanner.tickets_of_value - ~include_lazy - ~allow_zero_amount_tickets:true - ctxt - ty - value + Ticket_scanner.tickets_of_value ~include_lazy ctxt 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 Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step - >|? fun ctxt -> ((token, Script_int.to_zint amount) :: acc, ctxt)) + >|? fun ctxt -> + ( (token, Script_int.to_zint (amount :> Script_int.n Script_int.num)) + :: acc, + ctxt )) ([], ctxt) tickets >>?= fun (list, ctxt) -> Ticket_token_map.of_list ctxt list @@ -220,10 +218,7 @@ let update_ticket_balances ctxt ~self ~ticket_diffs operations = (Compare.Z.(Script_int.to_zint amount <= Z.neg balance_diff), ctxt) in (* Collect diffs from operations *) - Ticket_operations_diff.ticket_diffs_of_operations - ~allow_zero_amount_tickets:true - ctxt - operations + Ticket_operations_diff.ticket_diffs_of_operations ctxt operations >>=? fun (ticket_op_diffs, ctxt) -> (* Update balances for self-contract. *) Ticket_token_map.to_list ctxt ticket_diffs >>?= fun (ticket_diffs, ctxt) -> @@ -243,10 +238,11 @@ let update_ticket_balances ctxt ~self ~ticket_diffs operations = ~amount:(Script_int.to_zint total_amount)) >>?= fun () -> List.fold_left_e - (fun (acc, ctxt) (token, amount) -> + (fun (acc, ctxt) (token, (amount : Script_typed_ir.ticket_amount)) -> (* Consume some gas for for traversing the list. *) Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step - >|? fun ctxt -> ((token, Script_int.to_zint amount) :: acc, ctxt)) + >|? fun ctxt -> + ((token, Script_int.(to_zint (amount :> n num))) :: acc, ctxt)) ([], ctxt) destinations >>?= fun (destinations, ctxt) -> diff --git a/src/proto_alpha/lib_protocol/ticket_amount.ml b/src/proto_alpha/lib_protocol/ticket_amount.ml new file mode 100644 index 0000000000000000000000000000000000000000..9bc9cbbfebf6d7d0967f310c9f5c83b7b0f94d58 --- /dev/null +++ b/src/proto_alpha/lib_protocol/ticket_amount.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +open Script_int + +type t = n num + +let of_n n = + if Compare.Int.(Script_int.(compare n zero_n) > 0) then Some (n : t) else None + +let of_z z = Option.bind (is_nat z) of_n + +let of_zint z = of_z @@ of_zint z + +let add = add_n + +let sub a b = of_z @@ sub a b + +let one = one_n + +let encoding = + let open Data_encoding in + conv_with_guard + to_zint + (fun n -> Option.value_e ~error:"expecting positive number" @@ of_zint n) + n diff --git a/src/proto_alpha/lib_protocol/ticket_amount.mli b/src/proto_alpha/lib_protocol/ticket_amount.mli new file mode 100644 index 0000000000000000000000000000000000000000..191e0949cc706ee7ceef3c39ac3537d3fe04e61a --- /dev/null +++ b/src/proto_alpha/lib_protocol/ticket_amount.mli @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +open Script_int + +(* A type for ticket amount values to ensure positivity *) +type t = private n num + +val encoding : t Data_encoding.t + +(* Converts a natural number to a ticket amount value unless the input is zero *) +val of_n : n num -> t option + +(* Converts a integral number to a ticket amount value unless the input is not positive *) +val of_z : z num -> t option + +val of_zint : Z.t -> t option + +val add : t -> t -> t + +(* Subtract among ticket amount values unless the resultant amount is not positive *) +val sub : t -> t -> t option + +val one : t 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 cb495f2c4f161a5e2a24eb2944a2d21dbe695d7b..abc4fb54e37fde0ef24b29ba55ce2cf7c8091ca2 100644 --- a/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml +++ b/src/proto_alpha/lib_protocol/ticket_lazy_storage_diff.ml @@ -52,7 +52,7 @@ 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 - ((token, Script_int.to_zint amount), ctxt) + ((token, Script_int.(to_zint (amount :> n num))), ctxt) (** Extracts the ticket-token and amount from an ex_ticket value and returns the opposite of the amount. This is used to account for removal of tickets inside @@ -81,7 +81,6 @@ let collect_token_diffs_of_node ctxt has_tickets node ~get_token_and_amount acc (* It's currently not possible to have nested lazy structures, but this is for future proofing. *) ~include_lazy:true - ~allow_zero_amount_tickets:true has_tickets (Micheline.root node) >>=? fun (ex_tickets, ctxt) -> diff --git a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml index c3db21d23593a404f1a8875569d2ef5e2977c1af..1f545ae4c9ae830d10a2b9af329c0adaa91bd309 100644 --- a/src/proto_alpha/lib_protocol/ticket_operations_diff.ml +++ b/src/proto_alpha/lib_protocol/ticket_operations_diff.ml @@ -33,7 +33,7 @@ type ticket_transfer = { type ticket_token_diff = { ticket_token : Ticket_token.ex_token; total_amount : Script_int.n Script_int.num; - destinations : (Destination.t * Script_int.n Script_int.num) list; + destinations : (Destination.t * Ticket_amount.t) list; } type error += Failed_to_get_script of Contract.t | Contract_not_originated @@ -115,7 +115,7 @@ module Ticket_token_map = struct - The internal contract-indexed map cannot be empty. *) - let add ctxt ~ticket_token ~destination ~amount map = + let add ctxt ~ticket_token ~destination ~(amount : Ticket_amount.t) map = Ticket_token_map.update ctxt ticket_token @@ -129,12 +129,15 @@ module Ticket_token_map = struct (* Update the inner contract map *) let update ctxt prev_amt_opt = match prev_amt_opt with - | Some prev_amount -> + | Some (prev_amount : Ticket_amount.t) -> Gas.consume ctxt - (Ticket_costs.add_int_cost prev_amount amount) + Script_int.( + Ticket_costs.add_int_cost + (prev_amount :> n num) + (amount :> n num)) >|? fun ctxt -> - (Some (Script_int.add_n prev_amount amount), ctxt) + (Some (Ticket_amount.add prev_amount amount), ctxt) | None -> ok (Some amount, ctxt) in Destination_map.update ctxt destination update destination_map @@ -142,36 +145,24 @@ module Ticket_token_map = struct map end -let tickets_of_transaction ctxt ~allow_zero_amount_tickets ~destination - ~parameters_ty ~parameters = +let tickets_of_transaction ctxt ~destination ~parameters_ty ~parameters = Ticket_scanner.type_has_tickets ctxt parameters_ty >>?= fun (has_tickets, ctxt) -> - Ticket_scanner.tickets_of_value - ~include_lazy:true - ~allow_zero_amount_tickets - ctxt - has_tickets - parameters + Ticket_scanner.tickets_of_value ~include_lazy:true ctxt has_tickets parameters >>=? fun (tickets, ctxt) -> return (Some {destination; tickets}, ctxt) (** Extract tickets of an origination operation by scanning the storage. *) -let tickets_of_origination ctxt ~allow_zero_amount_tickets ~preorigination - ~storage_type ~storage = +let tickets_of_origination ctxt ~preorigination ~storage_type ~storage = (* Extract any tickets from the storage. Note that if the type of the contract storage does not contain tickets, storage is not scanned. *) Ticket_scanner.type_has_tickets ctxt storage_type >>?= fun (has_tickets, ctxt) -> - Ticket_scanner.tickets_of_value - ctxt - ~include_lazy:true - ~allow_zero_amount_tickets - has_tickets - storage + Ticket_scanner.tickets_of_value ctxt ~include_lazy:true has_tickets storage >|=? fun (tickets, ctxt) -> let destination = Destination.Contract (Originated preorigination) in (Some {tickets; destination}, ctxt) -let tickets_of_operation ctxt ~allow_zero_amount_tickets +let tickets_of_operation ctxt (Script_typed_ir.Internal_operation {source = _; operation; nonce = _}) = match operation with | Transaction_to_implicit _ -> return (None, ctxt) @@ -187,7 +178,6 @@ let tickets_of_operation ctxt ~allow_zero_amount_tickets } -> tickets_of_transaction ctxt - ~allow_zero_amount_tickets ~destination:(Destination.Contract (Originated destination)) ~parameters_ty ~parameters @@ -212,10 +202,8 @@ let tickets_of_operation ctxt ~allow_zero_amount_tickets unparsed_parameters = _; } -> (* Note that zero-amount tickets to a rollup is not permitted. *) - let allow_zero_amount_tickets = false in tickets_of_transaction ctxt - ~allow_zero_amount_tickets ~destination:(Destination.Sc_rollup destination) ~parameters_ty ~parameters @@ -229,12 +217,7 @@ let tickets_of_operation ctxt ~allow_zero_amount_tickets storage_type; storage; } -> - tickets_of_origination - ctxt - ~allow_zero_amount_tickets - ~preorigination - ~storage_type - ~storage + tickets_of_origination ctxt ~preorigination ~storage_type ~storage | Delegation _ | Event _ -> return (None, ctxt) let add_transfer_to_token_map ctxt token_map {destination; tickets} = @@ -247,11 +230,10 @@ let add_transfer_to_token_map ctxt token_map {destination; tickets} = (token_map, ctxt) tickets -let ticket_token_map_of_operations ctxt ~allow_zero_amount_tickets ops = +let ticket_token_map_of_operations ctxt ops = List.fold_left_es (fun (token_map, ctxt) op -> - tickets_of_operation ctxt ~allow_zero_amount_tickets op - >>=? fun (res, ctxt) -> + tickets_of_operation ctxt op >>=? fun (res, ctxt) -> match res with | Some ticket_trans -> add_transfer_to_token_map ctxt token_map ticket_trans @@ -260,9 +242,8 @@ let ticket_token_map_of_operations ctxt ~allow_zero_amount_tickets ops = ops (** Traverses a list of operations and scans for tickets. *) -let ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets operations = - ticket_token_map_of_operations ctxt ~allow_zero_amount_tickets operations - >>=? fun (token_map, ctxt) -> +let ticket_diffs_of_operations ctxt operations = + ticket_token_map_of_operations ctxt operations >>=? fun (token_map, ctxt) -> Ticket_token_map.fold ctxt (fun ctxt acc ticket_token destination_map -> @@ -270,9 +251,13 @@ let ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets operations = ticket-token. *) Destination_map.fold ctxt - (fun ctxt total_amount _destination amount -> - Gas.consume ctxt (Ticket_costs.add_int_cost total_amount amount) - >|? fun ctxt -> (Script_int.add_n total_amount amount, ctxt)) + (fun ctxt total_amount _destination (amount : Ticket_amount.t) -> + Gas.consume + ctxt + Script_int.( + Ticket_costs.add_int_cost total_amount (amount :> n num)) + >|? fun ctxt -> + (Script_int.(add_n total_amount (amount :> n num)), ctxt)) Script_int.zero_n destination_map >>? fun (total_amount, ctxt) -> diff --git a/src/proto_alpha/lib_protocol/ticket_operations_diff.mli b/src/proto_alpha/lib_protocol/ticket_operations_diff.mli index 79d35af1d6e82a0938d7b5a564b3f683e7bd1e0a..d413a81da9e62e7006cf75a22aa93162b845ce50 100644 --- a/src/proto_alpha/lib_protocol/ticket_operations_diff.mli +++ b/src/proto_alpha/lib_protocol/ticket_operations_diff.mli @@ -36,21 +36,19 @@ type ticket_token_diff = private { ticket_token : Ticket_token.ex_token; total_amount : Script_int.n Script_int.num; destinations : - (Alpha_context.Destination.t * Script_int.n Script_int.num) list; + (Alpha_context.Destination.t * Script_typed_ir.ticket_amount) list; } -(** [ticket_diffs_of_operations ctxt ~allow_zero_amount_tickets ops] returns a +(** [ticket_diffs_of_operations ctxt ops] returns a list of ticket-tokens diffs given a context, [ctxt], and list of packed operations, [ops]. The diffs result from either a [Transaction] operation with parameters containing tickets, or an [Origination] operation with the initial storage containing tickets. - The flag [allow_zero_amount_tickets] decides whether or not tickets with - amount zero are allowed. If the flag is set to [false] and a zero-amount - ticket is encountered, an {!Ticket_scanner.Forbidden_zero_ticket_quantity} - error is returned. *) + Tickets with amount zero are *not* allowed. If a zero-amount ticket is + encountered, a {!Ticket_scanner.Forbidden_zero_ticket_quantity} error is + returned. *) val ticket_diffs_of_operations : Alpha_context.context -> - allow_zero_amount_tickets:bool -> Script_typed_ir.packed_internal_operation list -> (ticket_token_diff list * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.ml b/src/proto_alpha/lib_protocol/ticket_scanner.ml index 84dcdc19bdce9cc2431d07acce5ab0c66c5b79f4..4993572e9fa717453a641bd7a7bd827c15b07977 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.ml +++ b/src/proto_alpha/lib_protocol/ticket_scanner.ml @@ -29,7 +29,6 @@ open Alpha_context type error += | (* Permanent *) Unsupported_non_empty_overlay | (* Permanent *) Unsupported_type_operation - | (* Permanent *) Forbidden_zero_ticket_quantity let () = register_error_kind @@ -51,16 +50,7 @@ let () = Format.fprintf ppf "Types embedding operations are not supported") Data_encoding.empty (function Unsupported_type_operation -> Some () | _ -> None) - (fun () -> Unsupported_type_operation) ; - register_error_kind - `Permanent - ~id:"forbidden_zero_amount_ticket" - ~title:"Zero ticket amount is not allowed" - ~description: - "It is not allowed to use a zero amount ticket in this operation." - Data_encoding.empty - (function Forbidden_zero_ticket_quantity -> Some () | _ -> None) - (fun () -> Forbidden_zero_ticket_quantity) + (fun () -> Unsupported_type_operation) type ex_ticket = | Ex_ticket : @@ -322,7 +312,6 @@ module Ticket_collection = struct let rec tickets_of_value : type a ac ret. include_lazy:bool -> - allow_zero_amount_tickets:bool -> context -> a Ticket_inspection.has_tickets -> (a, ac) Script_typed_ir.ty -> @@ -330,7 +319,7 @@ module Ticket_collection = struct accumulator -> ret continuation -> ret tzresult Lwt.t = - fun ~include_lazy ~allow_zero_amount_tickets ctxt hty ty x acc k -> + fun ~include_lazy ctxt hty ty x acc k -> let open Script_typed_ir in consume_gas_steps ctxt ~num_steps:1 >>?= fun ctxt -> match (hty, ty) with @@ -339,7 +328,6 @@ module Ticket_collection = struct let l, r = x in (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt hty1 ty1 @@ -348,7 +336,6 @@ module Ticket_collection = struct (fun ctxt acc -> (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt hty2 ty2 @@ -360,7 +347,6 @@ module Ticket_collection = struct | L v -> (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt htyl tyl @@ -370,7 +356,6 @@ module Ticket_collection = struct | R v -> (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt htyr tyr @@ -382,7 +367,6 @@ module Ticket_collection = struct | Some x -> (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt el_hty el_ty @@ -395,7 +379,6 @@ module Ticket_collection = struct (tickets_of_list [@ocaml.tailcall]) ctxt ~include_lazy - ~allow_zero_amount_tickets el_hty el_ty elements @@ -412,7 +395,6 @@ module Ticket_collection = struct (tickets_of_map [@ocaml.tailcall]) ctxt ~include_lazy - ~allow_zero_amount_tickets val_hty val_ty x @@ -420,41 +402,27 @@ module Ticket_collection = struct k) | Big_map_ht (_, val_hty), Big_map_t (key_ty, _, _) -> if include_lazy then - (tickets_of_big_map [@ocaml.tailcall]) - ctxt - ~allow_zero_amount_tickets - val_hty - key_ty - x - acc - k + (tickets_of_big_map [@ocaml.tailcall]) ctxt val_hty key_ty x acc k else (k [@ocaml.tailcall]) ctxt acc | True_ht, Ticket_t (comp_ty, _) -> - let Script_typed_ir.{ticketer = _; contents = _; amount} = x in - fail_when - ((not allow_zero_amount_tickets) - && Compare.Int.(Script_int.compare amount Script_int.zero_n = 0)) - Forbidden_zero_ticket_quantity - >>=? fun () -> (k [@ocaml.tailcall]) ctxt (Ex_ticket (comp_ty, x) :: acc) + (k [@ocaml.tailcall]) ctxt (Ex_ticket (comp_ty, x) :: acc) and tickets_of_list : type a ac ret. context -> include_lazy:bool -> - allow_zero_amount_tickets:bool -> a Ticket_inspection.has_tickets -> (a, ac) Script_typed_ir.ty -> a list -> accumulator -> ret continuation -> ret tzresult Lwt.t = - fun ctxt ~include_lazy ~allow_zero_amount_tickets el_hty el_ty elements acc k -> + fun ctxt ~include_lazy el_hty el_ty elements acc k -> consume_gas_steps ctxt ~num_steps:1 >>?= fun ctxt -> match elements with | elem :: elems -> (tickets_of_value [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt el_hty el_ty @@ -463,7 +431,6 @@ module Ticket_collection = struct (fun ctxt acc -> (tickets_of_list [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt el_hty el_ty @@ -475,7 +442,6 @@ module Ticket_collection = struct and tickets_of_map : type k v vc ret. include_lazy:bool -> - allow_zero_amount_tickets:bool -> context -> v Ticket_inspection.has_tickets -> (v, vc) Script_typed_ir.ty -> @@ -483,7 +449,7 @@ module Ticket_collection = struct accumulator -> ret continuation -> ret tzresult Lwt.t = - fun ~include_lazy ~allow_zero_amount_tickets ctxt val_hty val_ty map acc k -> + fun ~include_lazy ctxt val_hty val_ty map acc k -> let (module M) = Script_map.get_module map in consume_gas_steps ctxt ~num_steps:1 >>?= fun ctxt -> (* Pay gas for folding over the values *) @@ -491,7 +457,6 @@ module Ticket_collection = struct let values = M.OPS.fold (fun _ v vs -> v :: vs) M.boxed [] in (tickets_of_list [@ocaml.tailcall]) ~include_lazy - ~allow_zero_amount_tickets ctxt val_hty val_ty @@ -502,7 +467,6 @@ module Ticket_collection = struct and tickets_of_big_map : type k v ret. context -> - allow_zero_amount_tickets:bool -> v Ticket_inspection.has_tickets -> k Script_typed_ir.comparable_ty -> (k, v) Script_typed_ir.big_map -> @@ -510,7 +474,6 @@ module Ticket_collection = struct ret continuation -> ret tzresult Lwt.t = fun ctxt - ~allow_zero_amount_tickets val_hty key_ty (Big_map {id; diff = {map = _; size}; key_type = _; value_type}) @@ -539,7 +502,6 @@ module Ticket_collection = struct List.fold_left_es accum ([], ctxt) exps >>=? fun (values, ctxt) -> (tickets_of_list [@ocaml.tailcall]) ~include_lazy:true - ~allow_zero_amount_tickets ctxt val_hty value_type @@ -562,20 +524,13 @@ let type_has_tickets ctxt ty = Ticket_inspection.has_tickets_of_ty ctxt ty >|? fun (has_tickets, ctxt) -> (Has_tickets (has_tickets, ty), ctxt) -let tickets_of_value ctxt ~include_lazy ~allow_zero_amount_tickets - (Has_tickets (ht, ty)) = - Ticket_collection.tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets - ht - ty +let tickets_of_value ctxt ~include_lazy (Has_tickets (ht, ty)) = + Ticket_collection.tickets_of_value ctxt ~include_lazy ht ty let has_tickets (Has_tickets (ht, _)) = match ht with Ticket_inspection.False_ht -> false | _ -> true -let tickets_of_node ctxt ~include_lazy ~allow_zero_amount_tickets has_tickets - expr = +let tickets_of_node ctxt ~include_lazy has_tickets expr = let (Has_tickets (ht, ty)) = has_tickets in match ht with | Ticket_inspection.False_ht -> return ([], ctxt) @@ -587,9 +542,4 @@ let tickets_of_node ctxt ~include_lazy ~allow_zero_amount_tickets has_tickets ty expr >>=? fun (value, ctxt) -> - tickets_of_value - ctxt - ~include_lazy - ~allow_zero_amount_tickets - has_tickets - value + tickets_of_value ctxt ~include_lazy has_tickets value diff --git a/src/proto_alpha/lib_protocol/ticket_scanner.mli b/src/proto_alpha/lib_protocol/ticket_scanner.mli index bb6be0d5e850620f0ef5bae9be70f3904dcf8267..209c633ab74abb5a5dd1cd91cd5b3e93c6f01e3d 100644 --- a/src/proto_alpha/lib_protocol/ticket_scanner.mli +++ b/src/proto_alpha/lib_protocol/ticket_scanner.mli @@ -26,8 +26,6 @@ (** This module provides an API for extracting tickets of arbitrary types from an OCaml values, given a type-witness. *) -type error += (* Permanent *) Forbidden_zero_ticket_quantity - (** A type for representing existentially quantified tickets (tickets with different types of payloads). An [ex_ticket] value consists of: - A type-witness representing the type of the content of the ticket. @@ -65,7 +63,6 @@ val type_has_tickets : val tickets_of_value : Alpha_context.context -> include_lazy:bool -> - allow_zero_amount_tickets:bool -> 'a has_tickets -> 'a -> (ex_ticket list * Alpha_context.context) tzresult Lwt.t @@ -86,7 +83,6 @@ val tickets_of_value : val tickets_of_node : Alpha_context.context -> include_lazy:bool -> - allow_zero_amount_tickets:bool -> 'a has_tickets -> Alpha_context.Script.node -> (ex_ticket list * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/ticket_token.mli b/src/proto_alpha/lib_protocol/ticket_token.mli index ec048615d71a77e30336d32edc1066c46a0b23e6..164b51405756bf5965b5d194e5cd84b05636c2e4 100644 --- a/src/proto_alpha/lib_protocol/ticket_token.mli +++ b/src/proto_alpha/lib_protocol/ticket_token.mli @@ -41,4 +41,4 @@ type ex_token = (** [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_int.n Script_int.num + Ticket_scanner.ex_ticket -> ex_token * Script_typed_ir.ticket_amount diff --git a/src/proto_alpha/lib_protocol/tx_rollup_ticket.ml b/src/proto_alpha/lib_protocol/tx_rollup_ticket.ml index 368d6b9045598ffea6a725916fa0d1e2e220266a..1d03467e2972405355565447f809f06307ffc51e 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_ticket.ml +++ b/src/proto_alpha/lib_protocol/tx_rollup_ticket.ml @@ -55,17 +55,9 @@ let parse_ticket_and_operation ~consume_deserialization_gas ~ticketer ~contents let ticket_token = Ticket_token.Ex_token {ticketer; contents_type; contents} in - Option.value_e - ~error: - (Error_monad.trace_of_error - @@ Tx_rollup_errors.Internal_error - "Ticket quantity is negative, this can't happen because it comes \ - from a qty.") - Script_int.(is_nat @@ of_zint amount) - >>?= fun amount_node -> Script_typed_ir.ticket_t Micheline.dummy_location contents_type >>?= fun ticket_ty -> - let ticket = Script_typed_ir.{ticketer; contents; amount = amount_node} in + let ticket = Script_typed_ir.{ticketer; contents; amount} in Script_ir_translator.unparse_data ctxt Optimized ticket_ty ticket >>=? fun (parameters_expr, ctxt) -> Gas.consume ctxt (Script.strip_locations_cost parameters_expr) @@ -100,7 +92,9 @@ let make_withdraw_order ctxt tx_rollup ex_ticket claimer amount = in return (ctxt, withdrawal) -let transfer_ticket_with_hashes ctxt ~src_hash ~dst_hash qty = +let transfer_ticket_with_hashes ctxt ~src_hash ~dst_hash + (qty : Script_typed_ir.ticket_amount) = + let qty = Script_int.(to_zint (qty :> n num)) in Ticket_balance.adjust_balance ctxt src_hash ~delta:(Z.neg qty) >>=? fun (src_storage_diff, ctxt) -> Ticket_balance.adjust_balance ctxt dst_hash ~delta:qty diff --git a/src/proto_alpha/lib_protocol/tx_rollup_ticket.mli b/src/proto_alpha/lib_protocol/tx_rollup_ticket.mli index 77865d9e7dca569073b5f4825c9bf24785d1bf57..d900a644a817cede2cb0a2059e0471bd276bc12a 100644 --- a/src/proto_alpha/lib_protocol/tx_rollup_ticket.mli +++ b/src/proto_alpha/lib_protocol/tx_rollup_ticket.mli @@ -50,7 +50,7 @@ val parse_ticket_and_operation : source:Contract.t -> destination:Contract_hash.t -> entrypoint:Entrypoint.t -> - amount:Z.t -> + amount:Script_typed_ir.ticket_amount -> context -> (context * Ticket_token.ex_token * Script_typed_ir.packed_internal_operation) tzresult @@ -85,7 +85,7 @@ val transfer_ticket_with_hashes : context -> src_hash:Ticket_hash.t -> dst_hash:Ticket_hash.t -> - Z.t -> + Script_typed_ir.ticket_amount -> (context * Z.t) tzresult Lwt.t (** [transfer_ticket ctxt ~src ~dst ex_token qty] updates the table of @@ -100,5 +100,5 @@ val transfer_ticket : src:Destination.t -> dst:Destination.t -> Ticket_token.ex_token -> - counter -> + Script_typed_ir.ticket_amount -> (context * counter, error trace) result Lwt.t diff --git a/tests_python/contracts_alpha/ill_typed/ticket_in_ticket.tz b/tests_python/contracts_alpha/ill_typed/ticket_in_ticket.tz index ee6bdf2387230414a3f5958d59f427bf9e3c1830..ef6a1dcb49fe6b5b0b89a6e4d9b685a1d7bf0a45 100644 --- a/tests_python/contracts_alpha/ill_typed/ticket_in_ticket.tz +++ b/tests_python/contracts_alpha/ill_typed/ticket_in_ticket.tz @@ -9,6 +9,7 @@ code { PUSH nat 0; SWAP; TICKET; + ASSERT_SOME; READ_TICKET; CDR; CAR; SWAP; READ_TICKET; CDR; CAR; SWAP; DROP; diff --git a/tests_python/contracts_alpha/mini_scenarios/add_clear_tickets.tz b/tests_python/contracts_alpha/mini_scenarios/add_clear_tickets.tz index 9275b38a2c39c5d179921a14c15fae95316bd9e5..ed8cf6ce2b6d0b8ba1d46adf35851a35b275c288 100644 --- a/tests_python/contracts_alpha/mini_scenarios/add_clear_tickets.tz +++ b/tests_python/contracts_alpha/mini_scenarios/add_clear_tickets.tz @@ -2,5 +2,5 @@ parameter (or (pair %add nat string) (unit %clear)) ; storage (list (ticket string)) ; code { UNPAIR ; IF_LEFT - { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; CONS ; NIL operation ; PAIR } + { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; ASSERT_SOME ; CONS ; NIL operation ; PAIR } { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } diff --git a/tests_python/contracts_alpha/mini_scenarios/send_tickets_in_big_map.tz b/tests_python/contracts_alpha/mini_scenarios/send_tickets_in_big_map.tz index e8c27faf309805d39b5c8948e9d67f10bbad24ac..050d64cd607107258ddeb00cd90a53dc168832fd 100644 --- a/tests_python/contracts_alpha/mini_scenarios/send_tickets_in_big_map.tz +++ b/tests_python/contracts_alpha/mini_scenarios/send_tickets_in_big_map.tz @@ -27,6 +27,7 @@ code { CAR ; PUSH nat 1 ; PUSH string "BLUE" ; TICKET ; + ASSERT_SOME ; DIG 3 ; SWAP ; SOME ; diff --git a/tests_python/contracts_alpha/mini_scenarios/ticket_builder_fungible.tz b/tests_python/contracts_alpha/mini_scenarios/ticket_builder_fungible.tz index 674ae800771d99747ed8b1939bc4dcdcac588f19..17a0be3750ac62143367760fe9a7573beffb1154 100644 --- a/tests_python/contracts_alpha/mini_scenarios/ticket_builder_fungible.tz +++ b/tests_python/contracts_alpha/mini_scenarios/ticket_builder_fungible.tz @@ -32,7 +32,7 @@ code DUP @manager 2; SENDER; ASSERT_CMPEQ; UNPAIR; - SWAP; UNIT; TICKET; + SWAP; UNIT; TICKET; ASSERT_SOME; PUSH mutez 0; SWAP; TRANSFER_TOKENS; NIL operation; SWAP; CONS }; diff --git a/tests_python/contracts_alpha/mini_scenarios/ticket_builder_non_fungible.tz b/tests_python/contracts_alpha/mini_scenarios/ticket_builder_non_fungible.tz index ae669d17ad60e0225a8562ef8365321d95af3eff..df7e19a4f3498068b0ce4ab4c9dcb2ffa63346a4 100644 --- a/tests_python/contracts_alpha/mini_scenarios/ticket_builder_non_fungible.tz +++ b/tests_python/contracts_alpha/mini_scenarios/ticket_builder_non_fungible.tz @@ -34,7 +34,7 @@ code # Mint the token PUSH @amount nat 1; DUP @counter 4; - TICKET; + TICKET; ASSERT_SOME; # This is safe because the amount is not zero # Send it PUSH mutez 0; SWAP; TRANSFER_TOKENS; diff --git a/tests_python/contracts_alpha/opcodes/ticket_big_store.tz b/tests_python/contracts_alpha/opcodes/ticket_big_store.tz index 6d1de845235e41984b6882e6f43324a0a5723165..05cb7725bfaf58c6c1014b44537ae00b600d0f1e 100644 --- a/tests_python/contracts_alpha/opcodes/ticket_big_store.tz +++ b/tests_python/contracts_alpha/opcodes/ticket_big_store.tz @@ -1,3 +1,3 @@ parameter nat ; storage (big_map unit (ticket nat)); -code { UNPAIR ; PUSH nat 1 ; SWAP ; TICKET ; SOME ; UNIT ; UPDATE ; NIL operation ; PAIR } ; +code { UNPAIR ; PUSH nat 1 ; SWAP ; TICKET ; ASSERT_SOME; SOME ; UNIT ; UPDATE ; NIL operation ; PAIR } ; diff --git a/tests_python/contracts_alpha/opcodes/ticketer-2.tz b/tests_python/contracts_alpha/opcodes/ticketer-2.tz index bce940ccabe270ed748e9c49ba81489fde35b1ea..fe81daf476322f7317d55fd73ca89a57b2bebdaa 100644 --- a/tests_python/contracts_alpha/opcodes/ticketer-2.tz +++ b/tests_python/contracts_alpha/opcodes/ticketer-2.tz @@ -2,7 +2,7 @@ parameter (pair (pair address nat) nat) ; storage unit; code { CAR ; UNPAIR ; UNPAIR ; CONTRACT (ticket nat) ; ASSERT_SOME ; - DIP { TICKET } ; + DIP { TICKET ; ASSERT_SOME } ; SWAP ; DIP { PUSH mutez 0 } ; TRANSFER_TOKENS ; NIL operation ; SWAP ; CONS ; diff --git a/tests_python/contracts_alpha/opcodes/ticketer.tz b/tests_python/contracts_alpha/opcodes/ticketer.tz index c8ec4565398a43c462dcf9da9d03317e2b889563..d6660d1fe600cedd13f056f55dccf8fd9303b6f7 100644 --- a/tests_python/contracts_alpha/opcodes/ticketer.tz +++ b/tests_python/contracts_alpha/opcodes/ticketer.tz @@ -4,6 +4,7 @@ code { UNPAIR ; DIP { DUP } ; SWAP ; PUSH nat 1 ; SWAP ; TICKET ; + ASSERT_SOME ; DIP { CONTRACT (ticket nat) ; ASSERT_SOME ; PUSH mutez 0 } ; TRANSFER_TOKENS ; NIL operation ; SWAP ; CONS ; diff --git a/tests_python/contracts_alpha/opcodes/utxor.tz b/tests_python/contracts_alpha/opcodes/utxor.tz index 81d9632d35d27230d60c288afe9461ed32c5a026..1720512520c33b7e126f806118fe37022b0381e0 100644 --- a/tests_python/contracts_alpha/opcodes/utxor.tz +++ b/tests_python/contracts_alpha/opcodes/utxor.tz @@ -4,6 +4,7 @@ code { UNPAIR ; DIP { DUP } ; SWAP ; PUSH nat 5 ; SWAP ; TICKET ; + ASSERT_SOME ; PUSH nat 2 ; PUSH nat 3 ; PAIR ; SWAP ; SPLIT_TICKET ; diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_first_transfer.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_first_transfer.out index 692ca680088483586e78b34a0605679fac3cf219..f704ab041f3d4c86cd1809396d988f82560aebd9 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_first_transfer.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_first_transfer.out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestCreateRemoveTickets::test_add_clear_tickets_add_first_transfer Node is bootstrapped. -Estimated gas: 2576.032 units (will add 100 for safety) +Estimated gas: 2579.990 units (will add 100 for safety) Estimated storage: 105 bytes added (will add 20 for safety) Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' @@ -14,7 +14,7 @@ This sequence of operations was run: From: [CONTRACT_HASH] Fee to the baker: ꜩ0.000535 Expected counter: [EXPECTED_COUNTER] - Gas limit: 2677 + Gas limit: 2680 Storage limit: 125 bytes Balance updates: [CONTRACT_HASH] ... -ꜩ0.000535 @@ -27,10 +27,10 @@ This sequence of operations was run: Parameter: (Pair 1 "A") This transaction was successfully applied Updated storage: - { Pair 0x0134d794a355dbb7027075d278a68494e91c6709ed00 (Pair "A" 1) } - Storage size: 154 bytes + { Pair 0x01d15749b3c834ffbb675a2515090953c7dc0f432f00 (Pair "A" 1) } + Storage size: 180 bytes Paid storage size diff: 105 bytes - Consumed gas: 2576.032 + Consumed gas: 2579.990 Balance updates: [CONTRACT_HASH] ... -ꜩ0.02625 storage fees ........................... +ꜩ0.02625 diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_second_transfer.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_second_transfer.out index ccd1f9583c789d4b5f5cd90e54ac04f40ef0998f..3f68e78e2f560b9104ccde31a50706ac1d6fd777 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_second_transfer.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_second_transfer.out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestCreateRemoveTickets::test_add_clear_tickets_add_second_transfer Node is bootstrapped. -Estimated gas: 1657.462 units (will add 100 for safety) +Estimated gas: 1657.492 units (will add 100 for safety) Estimated storage: no bytes added Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' @@ -27,8 +27,8 @@ This sequence of operations was run: Parameter: (Pair 1 "B") This transaction was successfully applied Updated storage: - { Pair 0x0134d794a355dbb7027075d278a68494e91c6709ed00 (Pair "B" 1) } - Storage size: 154 bytes - Consumed gas: 1657.462 + { Pair 0x01d15749b3c834ffbb675a2515090953c7dc0f432f00 (Pair "B" 1) } + Storage size: 180 bytes + Consumed gas: 1657.492 Injected block at minimal timestamp diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_third_transfer.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_third_transfer.out index ad35a6c8f1310efda8bbc65b652b02e72ce4bdec..a706045dea235dd10afaa981f9f04053f429d39a 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_third_transfer.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_add_third_transfer.out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestCreateRemoveTickets::test_add_clear_tickets_add_third_transfer Node is bootstrapped. -Estimated gas: 2333.201 units (will add 100 for safety) +Estimated gas: 2333.231 units (will add 100 for safety) Estimated storage: 105 bytes added (will add 20 for safety) Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' @@ -27,11 +27,11 @@ This sequence of operations was run: Parameter: (Pair 1 "C") This transaction was successfully applied Updated storage: - { Pair 0x0134d794a355dbb7027075d278a68494e91c6709ed00 (Pair "C" 1) ; - Pair 0x0134d794a355dbb7027075d278a68494e91c6709ed00 (Pair "B" 1) } - Storage size: 193 bytes + { Pair 0x01d15749b3c834ffbb675a2515090953c7dc0f432f00 (Pair "C" 1) ; + Pair 0x01d15749b3c834ffbb675a2515090953c7dc0f432f00 (Pair "B" 1) } + Storage size: 219 bytes Paid storage size diff: 105 bytes - Consumed gas: 2333.201 + Consumed gas: 2333.231 Balance updates: [CONTRACT_HASH] ... -ꜩ0.02625 storage fees ........................... +ꜩ0.02625 diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_clear_transfer.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_clear_transfer.out index f462a647b1ef092d5395bd968653d6416b066c69..415e932bb96772dd4b1d64635ef93d65d0b73fd5 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_clear_transfer.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_clear_transfer.out @@ -26,7 +26,7 @@ This sequence of operations was run: Entrypoint: clear This transaction was successfully applied Updated storage: {} - Storage size: 115 bytes + Storage size: 141 bytes Consumed gas: 1845.841 Injected block at minimal timestamp diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_origination.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_origination.out index 55c8551ac7548f8756c292160c4f3e5ec2ca4713..7d952f8e2c5fb76ff5d301663b7036d8a73ddf2d 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_origination.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestCreateRemoveTickets::test_add_clear_tickets_origination.out @@ -1,8 +1,8 @@ tests_alpha/test_contract.py::TestCreateRemoveTickets::test_add_clear_tickets_origination Node is bootstrapped. -Estimated gas: 1427.437 units (will add 100 for safety) -Estimated storage: 372 bytes added (will add 20 for safety) +Estimated gas: 1432.985 units (will add 100 for safety) +Estimated storage: 398 bytes added (will add 20 for safety) Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' NOT waiting for the operation to be included. @@ -12,13 +12,13 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [CONTRACT_HASH] - Fee to the baker: ꜩ0.000498 + Fee to the baker: ꜩ0.000525 Expected counter: [EXPECTED_COUNTER] - Gas limit: 1528 - Storage limit: 392 bytes + Gas limit: 1533 + Storage limit: 418 bytes Balance updates: - [CONTRACT_HASH] ... -ꜩ0.000498 - payload fees(the block proposer) ....... +ꜩ0.000498 + [CONTRACT_HASH] ... -ꜩ0.000525 + payload fees(the block proposer) ....... +ꜩ0.000525 Origination: From: [CONTRACT_HASH] Credit: ꜩ200 @@ -27,19 +27,27 @@ This sequence of operations was run: storage (list (ticket string)) ; code { UNPAIR ; IF_LEFT - { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; CONS ; NIL operation ; PAIR } + { UNPAIR ; + DIG 2 ; + SWAP ; + DIG 2 ; + TICKET ; + ASSERT_SOME ; + CONS ; + NIL operation ; + PAIR } { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } Initial storage: {} No delegate for this contract This origination was successfully applied Originated contracts: [CONTRACT_HASH] - Storage size: 115 bytes - Paid storage size diff: 115 bytes - Consumed gas: 1427.437 + Storage size: 141 bytes + Paid storage size diff: 141 bytes + Consumed gas: 1432.985 Balance updates: - [CONTRACT_HASH] ... -ꜩ0.02875 - storage fees ........................... +ꜩ0.02875 + [CONTRACT_HASH] ... -ꜩ0.03525 + storage fees ........................... +ꜩ0.03525 [CONTRACT_HASH] ... -ꜩ0.06425 storage fees ........................... +ꜩ0.06425 [CONTRACT_HASH] ... -ꜩ200 diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestScriptHashRegression::test_contract_hash[client_regtest_custom_scrubber0].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestScriptHashRegression::test_contract_hash[client_regtest_custom_scrubber0].out index b9ecd1631d6dbc8adcee08c7fea3762468e93a2c..2665db42079e4019852c262e8857aca35551b36f 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestScriptHashRegression::test_contract_hash[client_regtest_custom_scrubber0].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestScriptHashRegression::test_contract_hash[client_regtest_custom_scrubber0].out @@ -63,7 +63,7 @@ exprtw4kigYCiREgky6KBKryS7JkaGih6ju8jkjaXtpdcWYrYukRKX [CONTRACT_PATH]/macros/pa exprtxutG1Nu8d198ebiCraNuQ8a6iYYqJYfGXq19aykNPB1uECc8w [CONTRACT_PATH]/macros/set_caddaadr.tz exprvCE6JDXrzEfZuxTQzSgxWXtxX5GoNxvidL84CN2TAm6Hk3kuK6 [CONTRACT_PATH]/macros/take_my_money.tz exprunGqZLZZwm9mY31NFGbBemCgXGevYqLRKdeRKQArPf824Npnni [CONTRACT_PATH]/macros/unpair_macro.tz -expru9ZhqLGykU3yRksBDWe4uDwxavSM19B8WfKukQA3fkgok4hGTE [CONTRACT_PATH]/mini_scenarios/add_clear_tickets.tz +expruwYQvEdTgNzbm3228Xp6srt9FbG2v7w2F8yVH7BCK1P2NJTJUi [CONTRACT_PATH]/mini_scenarios/add_clear_tickets.tz exprufRUAYF6r5QHQvK8CzWkKQcdvYkPx5fjEYzWPXc35Dry77KDT1 [CONTRACT_PATH]/mini_scenarios/authentication.tz exprtjdvZr5J7WfN4SyNgKueLnxX4fALUYJ4cmi675EHJdUu5yyg2n [CONTRACT_PATH]/mini_scenarios/big_map_entrypoints.tz exprtfWRfK4RoY8CF9VXvcHeBxizfjMMPAkLojfUTuoZkMSyiPKoyK [CONTRACT_PATH]/mini_scenarios/big_map_magic.tz @@ -92,9 +92,9 @@ exprvJ8zXaBkyXMhJ2eKtPwdwbg5NLrggvW8MEpVK3hk3nAe215PQ6 [CONTRACT_PATH]/mini_scen exprtuiYUMjM6d8XxPda1yfKeN61ko6riom35PzybC31NKXkVhgBQy [CONTRACT_PATH]/mini_scenarios/reveal_signed_preimage.tz expruB4maBvk1y4JaeSLpDXWC3zKiXK5QFYv4B3R5KfdGEt4B5VvTT [CONTRACT_PATH]/mini_scenarios/self_address_receiver.tz exprvTG7hjtWXeogStj3pzM1MCVcNg1q6KnivqNVzQjviUrJvsjfQn [CONTRACT_PATH]/mini_scenarios/self_address_sender.tz -expru1Ks3BYyWcJeiRxtPC2htppzguP4vDCh5ULwtvHxD8sbP24pQb [CONTRACT_PATH]/mini_scenarios/send_tickets_in_big_map.tz -expru9ASRmfbXX8Ajf5uDeiZDbNwonrCiS1e6UaDXUstKU3yuwQwdZ [CONTRACT_PATH]/mini_scenarios/ticket_builder_fungible.tz -exprtXrMgaXhLsw6ioNNPThqPF1yDyLjqGdJeB6yMRKLUQZfkTD6jy [CONTRACT_PATH]/mini_scenarios/ticket_builder_non_fungible.tz +expru6tUaVWpaR7D5invwY7inJnPZGPXTcDqFvirrHPMRxSeHki5Fz [CONTRACT_PATH]/mini_scenarios/send_tickets_in_big_map.tz +expruaFvFLsin2MWRuDkLRfe56pdPTUQ8RK9k1ks1rUTjBnwryPyPx [CONTRACT_PATH]/mini_scenarios/ticket_builder_fungible.tz +expruMFhigCZpXrGaL5sMyjGw5k7CanAa7XRkHFemCoCwMfJFJjDuD [CONTRACT_PATH]/mini_scenarios/ticket_builder_non_fungible.tz exprthFU1n1xhXLi4D2G4andPJsLcem1g1UtKiKJjXkCfVHztC393b [CONTRACT_PATH]/mini_scenarios/ticket_wallet_fungible.tz expruoGtEJH3sXXm2ruNG6DGTFE3GM6fjAS6fzDZKtdaMnRzHvi3Xd [CONTRACT_PATH]/mini_scenarios/ticket_wallet_non_fungible.tz exprtnBz8poqNTrK4rzTXZFKQx7HWpx4WidHB5wxcM2oTS8NcrkAUt [CONTRACT_PATH]/mini_scenarios/tzip4_view.tz @@ -276,14 +276,14 @@ exprv4UZUuBDCZZjtW5kaezZjaKqpi1GN6vxHsvQNNkFktnaEbDb1M [CONTRACT_PATH]/opcodes/s expruVuXhQmoBMzZjPeY7VQSuJxefBBTuPyNR7PGnYhwouo9zKg3T1 [CONTRACT_PATH]/opcodes/subset.tz exprtz2jbsXuMMPAXYAGJZqjuBp8iF38XadE3YuZoC2W5NkyhhHMuq [CONTRACT_PATH]/opcodes/tez_add_sub.tz exprugbVFDGWcSSozyN3EK3AcdwtPeES3ao45HNogWc5V8fsJ8NsSP [CONTRACT_PATH]/opcodes/ticket_bad.tz -exprtvedUmBuu66gdQXWpEJNQBU96bnUVQmrWWLAbcdsCLV4Rwa34K [CONTRACT_PATH]/opcodes/ticket_big_store.tz +expruwtzPEyCm4Vaq42Fct7QG5eD1MzXzkJbRqm6EVQH6YSV2QLkr1 [CONTRACT_PATH]/opcodes/ticket_big_store.tz expruqx789AMcKUYwDeeeRvSnwdCw8gMVvWA6vuzPzBQwBM2qcDXJB [CONTRACT_PATH]/opcodes/ticket_join.tz exprvMp1LX8aeyEq9NiMXGyD34J4offZDANGRwFTxoEWXumEsDdAP8 [CONTRACT_PATH]/opcodes/ticket_read.tz exprtvtEFi6v3awAwbHivJkjki6mDNivewiCBeJDJT78PqWtq7VyUD [CONTRACT_PATH]/opcodes/ticket_split.tz exprtifPFaLqHvR9uGWbeLj5r3YVBnKaawt12q3BMhM9wsUdM9dFNy [CONTRACT_PATH]/opcodes/ticket_store-2.tz exprvJGjz1EDdnAPWZQ7ZngDNDDDXnxA2VY6SHdHKu8LxqcVHd3E6z [CONTRACT_PATH]/opcodes/ticket_store.tz -expruhNaUWmTNpmFWSXUgf1ZjgcUXmjtXGaMumzteyFYzT9CMmU4wc [CONTRACT_PATH]/opcodes/ticketer-2.tz -exprvPfYzs3x1V67saypcaPGwj5rnuKsb3tFi2VtqX7gtP4W3sjfye [CONTRACT_PATH]/opcodes/ticketer.tz +exprvDjqte3hX8aieidgPA2qyPWA5eYuVrvb3KKZ8aYkeDotovgkQ4 [CONTRACT_PATH]/opcodes/ticketer-2.tz +exprvSU3oSiKqMLpWgBhwJZbEMDnvKiNW57MYQ8YG787N7jocXMEuR [CONTRACT_PATH]/opcodes/ticketer.tz expruhV9RSEPAtKAUhBbdTw5gPFdjcKk8zr7cVLSsGtmJuH3o7VXXo [CONTRACT_PATH]/opcodes/transfer_amount.tz expru3MSjYZRmQi3yiN6gYa4X6rs88XLWH4H8ivzrCvxs8z8cJfu4Z [CONTRACT_PATH]/opcodes/transfer_tokens.tz exprtbACDcFtDfEwsBA5LAG13uMRAjnQsFjzNELMS7jQ87bcqgdE6r [CONTRACT_PATH]/opcodes/uncomb.tz @@ -291,7 +291,7 @@ exprufJpS3BWpgv4QBaBEMucbn1jsVpdqEGLLMfXjDuKGPRGCpZUkj [CONTRACT_PATH]/opcodes/u exprtqjpmEs9GUjSEzJYSnN3skiCb8js2bY48R9Lhxk9JW1CKnm6VP [CONTRACT_PATH]/opcodes/unpair_field_annotation_mismatch.tz exprv4ACaZe4aECCfG93NGVVHbQBNQ5Atxtju5vWASZSEp5sLECcjg [CONTRACT_PATH]/opcodes/update_big_map.tz expruWzM36ATA3fAee4WHDS4vvMeewkwhya1fZaa6HFPbjwt9vvGpg [CONTRACT_PATH]/opcodes/utxo_read.tz -expru3YgRPQBAnTWgKytSMs3tRj7dMgtWUxo75b1pUFrTLscKy2byF [CONTRACT_PATH]/opcodes/utxor.tz +expruNCoB4n3KQTeXbDJWLwynT32T6dz2Nxw5f7SwaqRNkQSBog79A [CONTRACT_PATH]/opcodes/utxor.tz expruJxgC2Q8Ubt8tPyQbZ41j6w4b8yw5f6bxjrMMM81TmMC9x5Lrc [CONTRACT_PATH]/opcodes/view_fib.tz expru9EavkgPCUAwHccJf9j1t4aTTssPKoBkCqC4YNr12kxXSwqFqD [CONTRACT_PATH]/opcodes/view_mutual_recursion.tz exprv4QXQuZtQE7CpKyecjrXJ8U2ovU1qjUKtw37J6kAEmu3fAKyN5 [CONTRACT_PATH]/opcodes/view_op_add.tz diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map.out index cfa26de12043db8740231d314ff9623fc2a6aaf2..d05270c3ff67834cf89fb18ab5e8690ff62ea46f 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map.out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestSendTicketsInBigMap::test_send_tickets_in_big_map Node is bootstrapped. -Estimated gas: 100143.520 units (will add 100 for safety) +Estimated gas: 100150.481 units (will add 100 for safety) Estimated storage: 10767 bytes added (will add 20 for safety) Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' @@ -12,13 +12,13 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [CONTRACT_HASH] - Fee to the baker: ꜩ0.010321 + Fee to the baker: ꜩ0.010322 Expected counter: [EXPECTED_COUNTER] - Gas limit: 100244 + Gas limit: 100251 Storage limit: 10787 bytes Balance updates: - [CONTRACT_HASH] ... -ꜩ0.010321 - payload fees(the block proposer) ....... +ꜩ0.010321 + [CONTRACT_HASH] ... -ꜩ0.010322 + payload fees(the block proposer) ....... +ꜩ0.010322 Transaction: Amount: ꜩ0 From: [CONTRACT_HASH] @@ -28,109 +28,109 @@ This sequence of operations was run: Updated storage: Unit Updated big_maps: New temp(1) of type (big_map int (ticket string)) - Set temp(1)[22] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[48] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[20] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[67] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[30] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[33] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[42] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[13] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[50] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[84] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[44] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[41] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[4] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[73] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[5] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[28] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[19] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[9] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[86] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[76] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[8] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[97] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[80] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[45] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[87] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[1] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[26] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[38] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[65] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[99] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[69] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[2] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[81] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[82] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[64] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[92] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[90] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[98] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[37] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[66] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[32] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[71] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[51] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[56] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[14] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[12] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[85] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[47] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[74] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[18] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[10] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[35] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[96] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[27] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[77] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[62] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[58] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[25] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[94] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[60] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[7] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[53] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[11] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[17] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[83] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[72] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[6] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[88] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[75] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[3] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[70] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[52] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[95] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[68] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[78] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[23] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[79] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[59] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[100] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[24] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[21] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[49] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[93] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[39] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[63] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[55] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[15] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[16] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[31] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[43] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[29] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[54] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[89] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[36] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[46] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[91] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[61] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[34] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[57] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Set temp(1)[40] to (Pair 0x013fdf9fa7cb678c9c1da3bbfdd83a77ca36efa00300 (Pair "BLUE" 1)) - Storage size: 294 bytes + Set temp(1)[22] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[48] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[20] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[67] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[30] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[33] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[42] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[13] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[50] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[84] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[44] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[41] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[4] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[73] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[5] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[28] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[19] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[9] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[86] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[76] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[8] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[97] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[80] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[45] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[87] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[1] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[26] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[38] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[65] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[99] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[69] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[2] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[81] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[82] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[64] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[92] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[90] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[98] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[37] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[66] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[32] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[71] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[51] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[56] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[14] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[12] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[85] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[47] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[74] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[18] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[10] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[35] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[96] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[27] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[77] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[62] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[58] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[25] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[94] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[60] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[7] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[53] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[11] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[17] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[83] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[72] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[6] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[88] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[75] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[3] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[70] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[52] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[95] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[68] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[78] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[23] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[79] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[59] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[100] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[24] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[21] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[49] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[93] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[39] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[63] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[55] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[15] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[16] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[31] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[43] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[29] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[54] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[89] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[36] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[46] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[91] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[61] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[34] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[57] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Set temp(1)[40] to (Pair 0x019712e28563749c441ac346e7b697488f68059a2300 (Pair "BLUE" 1)) + Storage size: 320 bytes Paid storage size diff: 67 bytes - Consumed gas: 50522.350 + Consumed gas: 50529.311 Balance updates: [CONTRACT_HASH] ... -ꜩ0.01675 storage fees ........................... +ꜩ0.01675 diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map_originate.out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map_originate.out index 26ac386869da614d4fb50ab9beb95124b63fa44c..f1e983098a4a99fc4cd4853b0616325d98b761ae 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map_originate.out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestSendTicketsInBigMap::test_send_tickets_in_big_map_originate.out @@ -1,8 +1,8 @@ tests_alpha/test_contract.py::TestSendTicketsInBigMap::test_send_tickets_in_big_map_originate Node is bootstrapped. -Estimated gas: 1479.953 units (will add 100 for safety) -Estimated storage: 551 bytes added (will add 20 for safety) +Estimated gas: 1485.567 units (will add 100 for safety) +Estimated storage: 577 bytes added (will add 20 for safety) Operation successfully injected in the node. Operation hash is '[BLOCK_HASH]' NOT waiting for the operation to be included. @@ -12,13 +12,13 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [CONTRACT_HASH] - Fee to the baker: ꜩ0.000682 + Fee to the baker: ꜩ0.000709 Expected counter: [EXPECTED_COUNTER] - Gas limit: 1580 - Storage limit: 571 bytes + Gas limit: 1586 + Storage limit: 597 bytes Balance updates: - [CONTRACT_HASH] ... -ꜩ0.000682 - payload fees(the block proposer) ....... +ꜩ0.000682 + [CONTRACT_HASH] ... -ꜩ0.000709 + payload fees(the block proposer) ....... +ꜩ0.000709 Origination: From: [CONTRACT_HASH] Credit: ꜩ200 @@ -50,6 +50,7 @@ This sequence of operations was run: PUSH nat 1 ; PUSH string "BLUE" ; TICKET ; + ASSERT_SOME ; DIG 3 ; SWAP ; SOME ; @@ -72,12 +73,12 @@ This sequence of operations was run: This origination was successfully applied Originated contracts: [CONTRACT_HASH] - Storage size: 294 bytes - Paid storage size diff: 294 bytes - Consumed gas: 1479.953 + Storage size: 320 bytes + Paid storage size diff: 320 bytes + Consumed gas: 1485.567 Balance updates: - [CONTRACT_HASH] ... -ꜩ0.0735 - storage fees ........................... +ꜩ0.0735 + [CONTRACT_HASH] ... -ꜩ0.08 + storage fees ........................... +ꜩ0.08 [CONTRACT_HASH] ... -ꜩ0.06425 storage fees ........................... +ꜩ0.06425 [CONTRACT_HASH] ... -ꜩ200 diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--add_clear_tickets.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--add_clear_tickets.tz].out index e4d7ef6dd70b90063db8e2eb164f77bd10f9b50b..e4c1396edeecd9b8db12930b1109dfbf768cf9dc 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--add_clear_tickets.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--add_clear_tickets.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[mini_scenarios/add_clear_tickets.tz] Well typed -Gas remaining: 1039990.715 units remaining +Gas remaining: 1039988.509 units remaining { parameter (or (pair %add nat string) (unit %clear)) ; storage (list (ticket string)) ; code { UNPAIR @@ -16,7 +16,8 @@ Gas remaining: 1039990.715 units remaining DIG 2 /* [ string : nat : list (ticket string) ] */ ; TICKET - /* [ ticket string : list (ticket string) ] */ ; + /* [ option (ticket string) : list (ticket string) ] */ ; + ASSERT_SOME ; CONS /* [ list (ticket string) ] */ ; NIL operation diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--send_tickets_in_big_map.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--send_tickets_in_big_map.tz].out index bdfe87e4c2c8014356aa55145be8e7d3f31f34ae..01a8967082ccb477abe7e10b2c08de18544f8833 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--send_tickets_in_big_map.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--send_tickets_in_big_map.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[mini_scenarios/send_tickets_in_big_map.tz] Well typed -Gas remaining: 1039969.352 units remaining +Gas remaining: 1039967.113 units remaining { parameter address ; storage unit ; code { CAR @@ -76,8 +76,9 @@ Gas remaining: 1039969.352 units remaining /* [ string : nat : big_map int (ticket string) : int : int : contract (big_map int (ticket string)) ] */ ; TICKET - /* [ ticket string : big_map int (ticket string) : int : int + /* [ option (ticket string) : big_map int (ticket string) : int : int : contract (big_map int (ticket string)) ] */ ; + ASSERT_SOME ; DIG 3 /* [ int : ticket string : big_map int (ticket string) : int : contract (big_map int (ticket string)) ] */ ; diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_fungible.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_fungible.tz].out index 7f4476b13b1ba56d811a63f8911bc7fbf7193f59..3c5c447d53c4338f6e23af924629e855c18da17a 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_fungible.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_fungible.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[mini_scenarios/ticket_builder_fungible.tz] Well typed -Gas remaining: 1039976.245 units remaining +Gas remaining: 1039974.006 units remaining { parameter (or (ticket %burn unit) (pair %mint (contract %destination (ticket unit)) (nat %amount))) ; @@ -40,7 +40,8 @@ Gas remaining: 1039976.245 units remaining UNIT /* [ unit : nat : contract (ticket unit) : address ] */ ; TICKET - /* [ ticket unit : contract (ticket unit) : address ] */ ; + /* [ option (ticket unit) : contract (ticket unit) : address ] */ ; + ASSERT_SOME ; PUSH mutez 0 /* [ mutez : ticket unit : contract (ticket unit) : address ] */ ; SWAP diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_non_fungible.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_non_fungible.tz].out index 8851a7f9e691514255eaccd872277256488b598d..1752d084e47279e166cf567d26f3a82e1ca60dbe 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_non_fungible.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[mini_scenarios--ticket_builder_non_fungible.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[mini_scenarios/ticket_builder_non_fungible.tz] Well typed -Gas remaining: 1039973.758 units remaining +Gas remaining: 1039971.519 units remaining { parameter (or (ticket %burn nat) (contract %mint_destination (ticket nat))) ; storage (pair (address %manager) (nat %counter)) ; code { AMOUNT @@ -35,7 +35,8 @@ Gas remaining: 1039973.758 units remaining DUP @counter 4 /* [ nat : nat : contract (ticket nat) : address : nat ] */ ; TICKET - /* [ ticket nat : contract (ticket nat) : address : nat ] */ ; + /* [ option (ticket nat) : contract (ticket nat) : address : nat ] */ ; + ASSERT_SOME ; PUSH mutez 0 /* [ mutez : ticket nat : contract (ticket nat) : address : nat ] */ ; SWAP diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticket_big_store.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticket_big_store.tz].out index 67cb8462f56c3d25fe15aea0ac524b5ff64d94e0..d6caaeff2bbc313d733671ab28031d76ca70f385 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticket_big_store.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticket_big_store.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[opcodes/ticket_big_store.tz] Well typed -Gas remaining: 1039994.150 units remaining +Gas remaining: 1039991.976 units remaining { parameter nat ; storage (big_map unit (ticket nat)) ; code { UNPAIR @@ -11,7 +11,8 @@ Gas remaining: 1039994.150 units remaining SWAP /* [ nat : nat : big_map unit (ticket nat) ] */ ; TICKET - /* [ ticket nat : big_map unit (ticket nat) ] */ ; + /* [ option (ticket nat) : big_map unit (ticket nat) ] */ ; + ASSERT_SOME ; SOME /* [ option (ticket nat) : big_map unit (ticket nat) ] */ ; UNIT diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer-2.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer-2.tz].out index 94abe47b83a4ca27529714337d16d2b375e1eb66..58ee20944006e7ba85c58f6e5556f9304bfcee9f 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer-2.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer-2.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[opcodes/ticketer-2.tz] Well typed -Gas remaining: 1039988.434 units remaining +Gas remaining: 1039986.226 units remaining { parameter (pair (pair address nat) nat) ; storage unit ; code { CAR @@ -13,7 +13,7 @@ Gas remaining: 1039988.434 units remaining CONTRACT (ticket nat) /* [ option (contract (ticket nat)) : nat : nat ] */ ; ASSERT_SOME ; - DIP { TICKET /* [ ticket nat ] */ } + DIP { TICKET /* [ option (ticket nat) ] */ ; ASSERT_SOME } /* [ contract (ticket nat) : ticket nat ] */ ; SWAP /* [ ticket nat : contract (ticket nat) ] */ ; diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer.tz].out index 18d9f6cf3ee5c4db0c4605180efb738f15bbe994..85bbab8acce350e63c21c2c4da97917c74d629a4 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--ticketer.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[opcodes/ticketer.tz] Well typed -Gas remaining: 1039988.950 units remaining +Gas remaining: 1039986.744 units remaining { parameter address ; storage nat ; code { UNPAIR @@ -15,7 +15,8 @@ Gas remaining: 1039988.950 units remaining SWAP /* [ nat : nat : address : nat ] */ ; TICKET - /* [ ticket nat : address : nat ] */ ; + /* [ option (ticket nat) : address : nat ] */ ; + ASSERT_SOME ; DIP { CONTRACT (ticket nat) /* [ option (contract (ticket nat)) : nat ] */ ; ASSERT_SOME ; diff --git a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--utxor.tz].out b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--utxor.tz].out index 9a04b176993f03997410c3bb960ffc0f4cb7fcda..2c2adeed4c65a5112692fcae0003ac31b25ded8c 100644 --- a/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--utxor.tz].out +++ b/tests_python/tests_alpha/_regtest_outputs/test_contract.TestTypecheck::test_typecheck[opcodes--utxor.tz].out @@ -1,7 +1,7 @@ tests_alpha/test_contract.py::TestTypecheck::test_typecheck[opcodes/utxor.tz] Well typed -Gas remaining: 1039969.043 units remaining +Gas remaining: 1039966.804 units remaining { parameter (pair address address) ; storage nat ; code { UNPAIR @@ -15,7 +15,8 @@ Gas remaining: 1039969.043 units remaining SWAP /* [ nat : nat : pair address address : nat ] */ ; TICKET - /* [ ticket nat : pair address address : nat ] */ ; + /* [ option (ticket nat) : pair address address : nat ] */ ; + ASSERT_SOME ; PUSH nat 2 /* [ nat : ticket nat : pair address address : nat ] */ ; PUSH nat 3 diff --git a/tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz b/tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz index 4ac4fac5a4654c085ba96fd5f4813782f897eea3..ecea3a4f8c83fafcb11b4423ae465b5f22a96103 100644 --- a/tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz +++ b/tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz @@ -4,6 +4,7 @@ code { CAR; UNPAIR 4; TICKET; + ASSERT_SOME; PAIR; SWAP; CONTRACT %deposit (pair (ticket string) tx_rollup_l2_address); diff --git a/tezt/tests/contracts/proto_current_mainnet/tickets.tz b/tezt/tests/contracts/proto_current_mainnet/tickets.tz index 08adb63dc9d09d91bb7375126e539701e7df8d83..febaa100a6df8664f2ee563a7ea224e3f2006b69 100644 --- a/tezt/tests/contracts/proto_current_mainnet/tickets.tz +++ b/tezt/tests/contracts/proto_current_mainnet/tickets.tz @@ -1,3 +1,3 @@ parameter unit; storage (list (ticket string)); -code { CDR ; PUSH nat 1 ; PUSH string "Red" ; TICKET ; CONS ; NIL operation; PAIR } +code { CDR ; PUSH nat 1 ; PUSH string "Red" ; TICKET ; ASSERT_SOME ; CONS ; NIL operation; PAIR } diff --git a/tezt/tests/contracts/proto_current_mainnet/tx_rollup_deposit.tz b/tezt/tests/contracts/proto_current_mainnet/tx_rollup_deposit.tz new file mode 100644 index 0000000000000000000000000000000000000000..04ad6f7275411340b460a86cb4c847dce72dc0da --- /dev/null +++ b/tezt/tests/contracts/proto_current_mainnet/tx_rollup_deposit.tz @@ -0,0 +1,20 @@ +parameter (pair string nat tx_rollup_l2_address address); +storage unit; +code { + CAR; + UNPAIR 4; + TICKET; + PAIR; + SWAP; + CONTRACT %deposit (pair (ticket string) tx_rollup_l2_address); + ASSERT_SOME; + SWAP; + PUSH mutez 0; + SWAP; + TRANSFER_TOKENS; + UNIT; + NIL operation; + DIG 2; + CONS; + PAIR; + } diff --git a/tezt/tests/iticket_migration.ml b/tezt/tests/iticket_migration.ml new file mode 100644 index 0000000000000000000000000000000000000000..0bddb3a7f69b6574056c535be24095fc22f7ed17 --- /dev/null +++ b/tezt/tests/iticket_migration.ml @@ -0,0 +1,564 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Protocol + Invocation: dune exec tezt/tests/main.exe -- --file iticket_migration.ml + Subject: Checks the migration of ITicket in protocol Alpha, to make sure + that the old TICKET instruction is mapped to TICKET_DEPRECATED, + and the old contracts continue to function provided that they + avoid creating zero tickets. +*) + +(* This test originates a contract that creates a zero ticket with the old TICKET + instruction, performs a protocol upgrade and inspect the script to make sure + TICKET is mapped to TICKET_DEPRECATED. It also calls this contract which does + not mitigate creation of zero tickets and this call should fail. +*) +let test_ticket_migration ~blocks_per_cycle ~migration_level ~migrate_from + ~migrate_to = + Test.register + ~__FILE__ + ~title: + (Printf.sprintf + "ITicket migration at level %d from %s to %s" + migration_level + (Protocol.name migrate_from) + (Protocol.name migrate_to)) + ~tags:["protocol"; "migration"; "sandbox"] + @@ fun () -> + assert (migration_level >= blocks_per_cycle) ; + Log.info "Node starting" ; + let* node = + Node.init + ~patch_config: + (Node.Config_file.set_sandbox_network_with_user_activated_upgrades + [(migration_level, migrate_to)]) + [Synchronisation_threshold 0; Connections 0] + in + Log.info "Node initialized" ; + let* client = Client.(init ~endpoint:(Node node) ()) in + let* () = Client.activate_protocol ~protocol:migrate_from client in + Log.info "Protocol activated" ; + let* contract_id = + Client.( + originate_contract + ~init:"Unit" + ~burn_cap:Tez.one + ~alias:"ticket" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg: + {| + storage unit; + parameter unit; + code + { + DROP; + PUSH nat 0; + PUSH string "hello"; + TICKET; + DROP; + UNIT; + NIL operation; + PAIR + } + |} + client) + in + Log.info "Contract %s originated" contract_id ; + (* Bake until migration *) + let* () = repeat 2 (fun () -> Client.bake_for_and_wait client) in + let* code_before = + Client.(contract_code ~unparsing_mode:Optimized) contract_id client + in + Log.info "code: %s" code_before ; + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~arg:"Unit" + client + in + (* Ensure that we did migrate *) + let* migration_block = + RPC.Client.call client @@ RPC.get_chain_block_metadata ~block:"2" () + in + Log.info "Checking migration block consistency" ; + Check.( + (migration_block.protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected protocol = %R, got %L") ; + Check.( + (migration_block.next_protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected next_protocol = %R, got %L") ; + (* Test that we can still bake after migration *) + let rec wait_for_migration_block () = + let* () = Client.bake_for_and_wait client in + let* migration_block = + RPC.(Client.call client @@ get_chain_block_header ()) + in + let level = JSON.(migration_block |-> "level" |> as_int) in + if level >= migration_level then + RPC.( + Client.call client + @@ get_chain_block_metadata ~block:(string_of_int level) ()) + else wait_for_migration_block () + in + let* migration_block = wait_for_migration_block () in + Log.info + "protocol: %s, next_protocol: %s" + migration_block.protocol + migration_block.next_protocol ; + (* Bake one more time to complete the protocol upgrade *) + let* () = Client.bake_for_and_wait client in + let* code_after = + Client.(contract_code ~unparsing_mode:Optimized) contract_id client + in + Log.info "code: %s" code_after ; + Check.( + (code_after =~ rex "\\bTICKET_DEPRECATED\\s*;") + ~error_msg:"expecting TICKET_DEPRECATED instruction, got code %L") ; + (* This transfer is now expected to fail because the contract produces a zero + amount ticket. *) + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~arg:"Unit" + ~expect_failure:true + client + in + unit + +(* This test originates a contract that creates, extracts and splits tickets in storage. + It then performs a protocol upgrade and calls the contract again to ensure it is + still functioning. +*) +let test_ticket_migration_in_storage_with_zero_tickets ~blocks_per_cycle + ~migration_level ~migrate_from ~migrate_to = + Test.register + ~__FILE__ + ~title: + (Printf.sprintf + "ITicket migration at level %d with zero ticket in storage" + migration_level) + ~tags:["protocol"; "migration"; "sandbox"] + @@ fun () -> + assert (migration_level >= blocks_per_cycle) ; + Log.info "Node starting" ; + let* node = + Node.init + ~patch_config: + (Node.Config_file.set_sandbox_network_with_user_activated_upgrades + [(migration_level, migrate_to)]) + [Synchronisation_threshold 0; Connections 0] + in + Log.info "Node initialized" ; + let* client = Client.(init ~endpoint:(Node node) ()) in + let* () = Client.activate_protocol ~protocol:migrate_from client in + Log.info "Protocol activated" ; + let* contract_id = + Client.( + originate_contract + ~init:"{}" + ~burn_cap:Tez.one + ~alias:"ticket" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg: + {| + storage (list (ticket string)); + parameter (or (unit %push) (unit %pop)); + code + { + UNPAIR; + IF_LEFT + { + DROP; + # forge a ticket of amount 4 + PUSH nat 0; + PUSH string "hello"; + TICKET; + CONS; + } + { + DROP; + # decrement the ticket at the stack top by 1 + IF_CONS + { DROP } + { PUSH string "empty stack"; FAILWITH } + }; + NIL operation; + PAIR + } + |} + client) + in + Log.info "Contract %s originated" contract_id ; + (* Bake until migration *) + let* () = repeat 2 (fun () -> Client.bake_for_and_wait client) in + let* code_before = + Client.(contract_code ~unparsing_mode:Optimized) contract_id client + in + Log.info "code: %s" code_before ; + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~entrypoint:"push" + ~arg:"Unit" + client + in + (* Ensure that we did migrate *) + let* migration_block = + RPC.Client.call client @@ RPC.get_chain_block_metadata ~block:"2" () + in + Log.info "Checking migration block consistency" ; + Check.( + (migration_block.protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected protocol = %R, got %L") ; + Check.( + (migration_block.next_protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected next_protocol = %R, got %L") ; + (* Test that we can still bake after migration *) + let rec wait_for_migration_block () = + let* () = Client.bake_for_and_wait client in + let* migration_block = + RPC.(Client.call client @@ get_chain_block_header ()) + in + let level = JSON.(migration_block |-> "level" |> as_int) in + if level >= migration_level then + RPC.( + Client.call client + @@ get_chain_block_metadata ~block:(string_of_int level) ()) + else wait_for_migration_block () + in + let* migration_block = wait_for_migration_block () in + Log.info + "protocol: %s, next_protocol: %s" + migration_block.protocol + migration_block.next_protocol ; + (* Bake one more time to complete the protocol upgrade *) + let* () = Client.bake_for_and_wait client in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~entrypoint:"pop" + ~expect_failure:true + ~arg:"Unit" + client + in + unit + +(* This test originates a contract that creates, extracts and splits tickets in storage. + It then performs a protocol upgrade and calls the contract again to ensure it is + still functioning. +*) +let test_ticket_migration_in_storage ~blocks_per_cycle ~migration_level + ~migrate_from ~migrate_to = + Test.register + ~__FILE__ + ~title:(Printf.sprintf "ITicket migration at level %d" migration_level) + ~tags:["protocol"; "migration"; "sandbox"] + @@ fun () -> + assert (migration_level >= blocks_per_cycle) ; + Log.info "Node starting" ; + let* node = + Node.init + ~patch_config: + (Node.Config_file.set_sandbox_network_with_user_activated_upgrades + [(migration_level, migrate_to)]) + [Synchronisation_threshold 0; Connections 0] + in + Log.info "Node initialized" ; + let* client = Client.(init ~endpoint:(Node node) ()) in + let* () = Client.activate_protocol ~protocol:migrate_from client in + Log.info "Protocol activated" ; + let* contract_id = + Client.( + originate_contract + ~init:"{}" + ~burn_cap:Tez.one + ~alias:"ticket" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg: + {| + storage (list (ticket string)); + parameter (or (unit %forge) (unit %split)); + code + { + UNPAIR; + IF_LEFT + { + DROP; + # forge a ticket of amount 4 + PUSH nat 4; + PUSH string "hello"; + TICKET; + CONS; + } + { + DROP; + # decrement the ticket at the stack top by 1 + IF_CONS + { + READ_TICKET; + GET 4; + PUSH nat 1; + SWAP; + SUB; + DUP; + # drop the ticket if it will go down to 0 + EQ; + IF + { DROP 2 } + { + ISNAT; + ASSERT_SOME; + PUSH nat 1; + PAIR; + SWAP; + SPLIT_TICKET; + ASSERT_SOME; + CDR; + CONS + } + } + { PUSH string "empty stack"; FAILWITH } + }; + NIL operation; + PAIR + } + |} + client) + in + Log.info "Contract %s originated" contract_id ; + (* Bake until migration *) + let* () = repeat 2 (fun () -> Client.bake_for_and_wait client) in + let* code_before = + Client.(contract_code ~unparsing_mode:Optimized) contract_id client + in + Log.info "code: %s" code_before ; + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~entrypoint:"forge" + ~arg:"Unit" + client + in + (* Ensure that we did migrate *) + let* migration_block = + RPC.Client.call client @@ RPC.get_chain_block_metadata ~block:"2" () + in + Log.info "Checking migration block consistency" ; + Check.( + (migration_block.protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected protocol = %R, got %L") ; + Check.( + (migration_block.next_protocol = Protocol.hash migrate_from) + string + ~error_msg:"expected next_protocol = %R, got %L") ; + (* Test that we can still bake after migration *) + let rec wait_for_migration_block () = + let* () = Client.bake_for_and_wait client in + let* migration_block = + RPC.(Client.call client @@ get_chain_block_header ()) + in + let level = JSON.(migration_block |-> "level" |> as_int) in + if level >= migration_level then + RPC.( + Client.call client + @@ get_chain_block_metadata ~block:(string_of_int level) ()) + else wait_for_migration_block () + in + let* migration_block = wait_for_migration_block () in + Log.info + "protocol: %s, next_protocol: %s" + migration_block.protocol + migration_block.next_protocol ; + (* Bake one more time to complete the protocol upgrade *) + let* () = Client.bake_for_and_wait client in + let* code_after = + Client.(contract_code ~unparsing_mode:Optimized) contract_id client + in + Log.info "code: %s" code_after ; + Check.( + (code_after =~ rex "\\bTICKET_DEPRECATED\\s*;") + ~error_msg:"expecting TICKET_DEPRECATED instruction, got code %L") ; + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~entrypoint:"forge" + ~arg:"Unit" + client + in + let* () = Client.bake_for_and_wait client in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~entrypoint:"split" + ~arg:"Unit" + client + in + unit + +(* This test activates Alpha protocol and asserts that it is impossible to + originate contracts containing the deprecated TICKET instruction. +*) +let test_iticket_deprecation ~protocol = + Test.register + ~__FILE__ + ~title:(Printf.sprintf "ITicket deprecation") + ~tags:["protocol"; "migration"; "sandbox"] + @@ fun () -> + let* _, client = Client.init_with_protocol `Client ~protocol () in + let* _ = Client.gen_and_show_keys client in + let process = + Client.( + spawn_originate_contract + ~init:"Unit" + ~burn_cap:Tez.one + ~alias:"ticket" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~log_output:true + ~prg: + {| + storage unit; + parameter unit; + code + { + DROP; + PUSH nat 0; + PUSH string "hello"; + TICKET_DEPRECATED; + DROP; + UNIT; + NIL operation; + PAIR + } + |} + client) + in + Process.check_error + ~msg:(rex "Use of deprecated instruction: TICKET_DEPRECATED") + process + +(* This test checks that after migration, the new ITicket instruction pushes + an option, and it correctly pushes some ticket if the ticket is well-formed.*) +let test_iticket_after_migration ~protocol = + Test.register + ~__FILE__ + ~title:(Printf.sprintf "ITicket semantics after migration") + ~tags:["protocol"; "migration"; "sandbox"] + @@ fun () -> + let* _, client = Client.init_with_protocol `Client ~protocol () in + let* _ = Client.gen_and_show_keys client in + let* contract_id = + Client.( + originate_contract + ~init:"{}" + ~burn_cap:Tez.one + ~alias:"ticket" + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~prg: + {| + storage (list (ticket string)); + parameter unit; + code + { + CDR; + PUSH nat 1; + PUSH string "hello"; + TICKET; + ASSERT_SOME; + CONS; + NIL operation; + PAIR + } + |} + client) + in + let* () = Client.bake_for_and_wait client in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.zero + ~giver:Constant.bootstrap1.alias + ~receiver:contract_id + ~arg:"Unit" + client + in + unit + +let register ~migrate_from ~migrate_to = + let parameters = JSON.parse_file (Protocol.parameter_file migrate_to) in + let blocks_per_cycle = JSON.(get "blocks_per_cycle" parameters |> as_int) in + match migrate_to with + | Protocol.Alpha -> + test_ticket_migration + ~blocks_per_cycle + ~migration_level:(2 * blocks_per_cycle) + ~migrate_from + ~migrate_to ; + test_iticket_deprecation ~protocol:Protocol.Alpha ; + test_ticket_migration_in_storage + ~blocks_per_cycle + ~migration_level:(2 * blocks_per_cycle) + ~migrate_from + ~migrate_to ; + test_ticket_migration_in_storage_with_zero_tickets + ~blocks_per_cycle + ~migration_level:(2 * blocks_per_cycle) + ~migrate_from + ~migrate_to ; + test_iticket_after_migration ~protocol:Protocol.Alpha + | _ -> () diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index e1368643c4debc1eeb813d0a572c629e11bc1ecd..05e79ecf4db9a90629b588842659d5bc8c8cbf3a 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -79,7 +79,8 @@ let register_protocol_migration_tests () = Voting.register ~from_protocol:migrate_to ~to_protocol:Demo - ~loser_protocols:[migrate_from] + ~loser_protocols:[migrate_from] ; + Iticket_migration.register ~migrate_from ~migrate_to let register_protocol_agnostic_tests () = (* Tests that are relatively protocol-agnostic. diff --git a/tezt/tests/tx_rollup.ml b/tezt/tests/tx_rollup.ml index 034cdfd4a6d192d9b29a4fd6e585cdb304c521c5..938547c0cf6afa7e9bba9c1a2cfd7735468039ad 100644 --- a/tezt/tests/tx_rollup.ml +++ b/tezt/tests/tx_rollup.ml @@ -1542,7 +1542,12 @@ let test_deposit_withdraw_max_big_tickets = ~alias:"deposit_contract" ~amount:Tez.zero ~src:account - ~prg:"file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + ~prg: + (match protocol with + | Alpha -> + "file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + | _ -> + "file:./tezt/tests/contracts/proto_current_mainnet/tx_rollup_deposit.tz") ~init:"Unit" ~burn_cap:Tez.one client diff --git a/tezt/tests/tx_rollup_l2_node.ml b/tezt/tests/tx_rollup_l2_node.ml index 8f974039fcb5d3ef1442ebdb88eb9bc4bdaca793..1c77a03d42c0d37789da73620b1fdd53bd6df058 100644 --- a/tezt/tests/tx_rollup_l2_node.ml +++ b/tezt/tests/tx_rollup_l2_node.ml @@ -26,7 +26,7 @@ (* Testing ------- Component: Tx_rollup_node - Invocation: dune exec tezt/tests/main.exe -- --file tx_rollup_node.ml + Invocation: dune exec tezt/tests/main.exe -- --file tx_rollup_l2_node.ml Subject: Various test scenarios for the Tx rollup node *) @@ -846,6 +846,13 @@ let get_ticket_hash_from_deposit (d : Tx_rollup_node.Inbox.message) : string = let get_ticket_hash_from_deposit_json inbox = JSON.(inbox |=> 0 |-> "message" |-> "deposit" |-> "ticket_hash" |> as_string) +let choose_deposit_contract_by_protocol ~protocol = + match protocol with + | Protocol.Alpha -> + "file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + | _ -> + "file:./tezt/tests/contracts/proto_current_mainnet/tx_rollup_deposit.tz" + (* Checks that the a ticket can be transfered from the L1 to the rollup. *) let test_ticket_deposit_from_l1_to_l2 = Protocol.register_test @@ -872,7 +879,7 @@ let test_ticket_deposit_from_l1_to_l2 = ~alias:"rollup_deposit" ~amount:Tez.zero ~src:"bootstrap1" - ~prg:"file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + ~prg:(choose_deposit_contract_by_protocol ~protocol) ~init:"Unit" ~burn_cap:Tez.(of_int 1) client @@ -1039,7 +1046,7 @@ let test_l2_to_l2_transaction = ~alias:"rollup_deposit" ~amount:Tez.zero ~src:"bootstrap1" - ~prg:"file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + ~prg:(choose_deposit_contract_by_protocol ~protocol) ~init:"Unit" ~burn_cap:Tez.(of_int 1) client @@ -1241,14 +1248,14 @@ let get_ticket_hash_from_op op = (** Originate a contract and make a deposit for [dest] and optionally for a list of destination in [dests]. *) -let make_deposit ~source ~tx_rollup_hash ~tx_node ~client ?(dests = []) - ~tickets_amount dest = +let make_deposit ~protocol ~source ~tx_rollup_hash ~tx_node ~client + ?(dests = []) ~tickets_amount dest = let* contract_id = Client.originate_contract ~alias:"rollup_deposit" ~amount:Tez.zero ~src:source - ~prg:"file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + ~prg:(choose_deposit_contract_by_protocol ~protocol) ~init:"Unit" ~burn_cap:Tez.(of_int 1) client @@ -1332,6 +1339,7 @@ let test_batcher ~test_persistence = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -1582,6 +1590,7 @@ let test_reorganization = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -1701,6 +1710,7 @@ let test_l2_proof_rpc_position = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -1905,6 +1915,7 @@ let test_reject_bad_commitment = let pkh1_str = bls_key1.aggregate_public_key_hash in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2015,6 +2026,7 @@ let test_committer = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* tzlevel, _ = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2135,6 +2147,7 @@ let test_tickets_context = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* _level, contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2268,6 +2281,7 @@ let test_round_trip ~title ?before_init ~originator ~operator ~batch_signer let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* _level, deposit_contract = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2482,6 +2496,7 @@ let test_accuser = let bls_pkh_1 = bls_key_1.aggregate_public_key_hash in let* _level, _deposit_contract = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2610,6 +2625,7 @@ let test_transfer_command = let* bls_key_2 = Client.bls_gen_and_show_keys client in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2677,6 +2693,7 @@ let test_withdraw_command = let* bls_key_1 = Client.bls_gen_and_show_keys client in let* _level, _contract_id = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2753,6 +2770,7 @@ let test_catch_up = let bls_pkh_2 = bls_key_2.aggregate_public_key_hash in let* tzlevel, _deposit_contract = make_deposit + ~protocol ~source:Constant.bootstrap2.public_key_hash ~tx_rollup_hash ~tx_node @@ -2831,7 +2849,7 @@ let test_origination_deposit_same_block = ~alias:"rollup_deposit" ~amount:Tez.zero ~src:"bootstrap1" - ~prg:"file:./tezt/tests/contracts/proto_alpha/tx_rollup_deposit.tz" + ~prg:(choose_deposit_contract_by_protocol ~protocol) ~init:"Unit" ~burn_cap:Tez.(of_int 1) client