diff --git a/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml b/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml index 30bc30ab0bc0c5528a72147f161c2495165e2616..74ef41ec164334dcd4a44ccc452f1bde2ba5f68c 100644 --- a/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml +++ b/src/proto_alpha/lib_benchmarks_proto/interpreter_workload.ml @@ -1278,6 +1278,9 @@ module Instructions = struct let halt = ir_sized_step N_IHalt nullary let log = ir_sized_step N_ILog nullary + + (* TODO: Joel set gas amount *) + let increment_global_counter = ir_sized_step N_ILog nullary end module Control = struct @@ -1753,6 +1756,8 @@ let extract_ir_sized_step : Instructions.halt | (ILog _, _) -> Instructions.log + | (IIncrement_global_counter _, _) -> + Instructions.increment_global_counter let extract_control_trace (type bef_top bef aft_top aft) (cont : (bef_top, bef, aft_top, aft) Script_typed_ir.continuation) = diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index 512868659ccf2240ad0c276bd9dc71f98106c93b..ac30b84114752eea8b3d86202ac989a3cc56d3ff 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -33,6 +33,9 @@ open Client_keys let get_balance (rpc : #rpc_context) ~chain ~block contract = Alpha_services.Contract.balance rpc (chain, block) contract +let get_global_counter (rpc : #rpc_context) ~chain ~block = + Alpha_services.Global_variables.get_global_counter rpc (chain, block) () + let get_storage (rpc : #rpc_context) ~chain ~block ~unparsing_mode contract = Plugin.RPC.Contract.get_storage_normalized rpc @@ -145,6 +148,44 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return ((oph, op, result), contracts) +let build_incremenent_global_counter_operation ?fee ?gas_limit () = + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option None) + Global_counter_increment + +let increment_global_counter (cctxt : #full) ~chain ~block ?confirmations + ?dry_run ?verbose_signing ?branch ~source ~src_pk ~src_sk ?fee ?gas_limit + ?counter ~fee_parameter () = + let contents = + build_incremenent_global_counter_operation ?fee ?gas_limit () + in + let contents = Annotated_manager_operation.Single_manager contents in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option None) + ?counter + ~src_pk + ~src_sk + ~fee_parameter + contents + >>=? fun (oph, op, result) -> + Lwt.return (Injection.originated_contracts result) + >>=? fun contracts -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return ((oph, op, result), contracts) + let build_reveal_operation ?fee ?gas_limit ?storage_limit pk = let operation = Reveal pk in Injection.prepare_manager_operation diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index c5255c31b5f06624b326106d6d300a7c30e28a25..8929a428397133060e13c8c5a6f453e11445f9b9 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -79,6 +79,12 @@ val get_balance : Contract.t -> Tez.t tzresult Lwt.t +val get_global_counter : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + int32 tzresult Lwt.t + val build_delegate_operation : ?fee:Tez.t -> ?gas_limit:Gas.Arith.integral -> @@ -181,6 +187,31 @@ val transfer : (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult Lwt.t +val increment_global_counter : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + ?fee:Tez.t -> + ?gas_limit:Fixed_point_repr.integral_tag Gas.Arith.t -> + ?counter:counter -> + fee_parameter:Injection.fee_parameter -> + unit -> + ( ( Operation_hash.t + * Kind.global_counter_increment Kind.manager contents + * Kind.global_counter_increment Kind.manager Apply_results.contents_result + ) + * Contract.t trace, + error trace ) + result + Lwt.t + val build_reveal_operation : ?fee:Tez.t -> ?gas_limit:Gas.Arith.integral -> diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 6dc8d6e68fdd06276f95f0ce888c736f50572487..8ae29673669f42d952139c407a6679de41990090 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -335,6 +335,8 @@ let estimated_gas_single (type kind) Ok consumed_gas | Applied (Delegation_result {consumed_gas}) -> Ok consumed_gas + | Applied (Global_counter_increment_result {consumed_gas}) -> + Ok consumed_gas | Skipped _ -> assert false | Backtracked (_, None) -> @@ -368,6 +370,8 @@ let estimated_storage_single (type kind) origination_size Ok Z.zero | Applied (Delegation_result _) -> Ok Z.zero + | Applied (Global_counter_increment_result _) -> + Ok Z.zero | Skipped _ -> assert false | Backtracked (_, None) -> @@ -413,6 +417,8 @@ let originated_contracts_single (type kind) Ok [] | Applied (Delegation_result _) -> Ok [] + | Applied (Global_counter_increment_result _) -> + Ok [] | Skipped _ -> assert false | Backtracked (_, None) -> diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 39cde840a0ff4927469a2da7a2b36d6cc9b91263..d9857f61ed097b1502718f1ac6ce745e406513df 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -130,7 +130,9 @@ let pp_manager_operation_content (type kind) source internal pp_result ppf Signature.Public_key_hash.pp delegate pp_result - result ) ; + result + | Global_counter_increment -> + Format.fprintf ppf "Increment global counter" ) ; Format.fprintf ppf "@]" let pp_balance_updates ppf = function @@ -319,6 +321,11 @@ let pp_manager_operation_contents_and_result ppf | Applied (Delegation_result {consumed_gas}) -> Format.fprintf ppf "This delegation was successfully applied" ; Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + | Applied (Global_counter_increment_result {consumed_gas}) -> + Format.fprintf + ppf + "This increment counter operation was succesfully applied" ; + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas | Backtracked (Delegation_result _, _) -> Format.fprintf ppf @@ -327,6 +334,11 @@ let pp_manager_operation_contents_and_result ppf | Applied (Transaction_result _ as tx) -> Format.fprintf ppf "This transaction was successfully applied" ; pp_transaction_result tx + | Backtracked (Global_counter_increment_result _, _) -> + Format.fprintf + ppf + "@[This increment global counter transaction was BACKTRACKED, \ + its expected effects were NOT applied.@]" | Backtracked ((Transaction_result _ as tx), _errs) -> Format.fprintf ppf diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index d21fbd37dfa438ea110a92c4c5c2a005807e3ee6..1a8cda28bf303eb89db7e3928e48a8968b4d7b93 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 @@ -114,6 +114,60 @@ let alphanet = {Clic.name = "alphanet"; title = "Alphanet only commands"} let binary_description = {Clic.name = "description"; title = "Binary Description"} +let increment_global_counter_command source cctxt + ( fee, + dry_run, + verbose_signing, + gas_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) = + let fee_parameter = + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + } + in + ( match Contract.is_implicit source with + | None -> + Managed_contract.get_contract_manager cctxt source + >>=? fun source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> return (src_pk, src_sk, source) + | Some source -> + Client_keys.get_key cctxt source + >>=? fun (_, src_pk, src_sk) -> return (src_pk, src_sk, source) ) + >>=? fun (src_pk, src_sk, source) -> + Client_proto_context.increment_global_counter + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ?gas_limit + ?counter + () + >>= report_michelson_errors + ~no_print_source + ~msg:"increment global counter simulation failed" + cctxt + >>= function None -> return_unit | Some (_res, _contracts) -> return_unit + let transfer_command amount source destination cctxt ( fee, dry_run, @@ -303,6 +357,14 @@ let commands network () = >>=? fun amount -> cctxt#answer "%a %s" Tez.pp amount Client_proto_args.tez_sym >>= fun () -> return_unit); + command + ~group + ~desc:"Get the global counter." + no_options + (prefixes ["get"; "global-counter"] stop) + (fun () (cctxt : Protocol_client_context.full) -> + get_global_counter cctxt ~chain:cctxt#chain ~block:cctxt#block + >>=? fun count -> cctxt#answer "%ld" count >>= fun () -> return_unit); command ~group ~desc:"Get the storage of a contract." @@ -1003,6 +1065,57 @@ let commands network () = fee_cap, burn_cap, entrypoint )); + (* Increment global counter command *) + command + ~group + ~desc:"Increment global counter." + (args12 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + counter_arg + no_print_source_flag + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg) + ( prefixes ["increment-global-counter"] + @@ ContractAlias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop ) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) + (_, source) + cctxt -> + increment_global_counter_command + source + cctxt + ( fee, + dry_run, + verbose_signing, + gas_limit, + counter, + no_print_source, + minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap )); command ~group ~desc:"Call a smart contract (same as 'transfer 0')." diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 23b46fcda0b95783b5572044e5fce18f62a38154..f1a7747d4a1fd63a4066998299597ad01e03202f 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -312,5 +312,12 @@ let get_rewards = Raw_context.get_rewards let description = Raw_context.description +let global_counter ctx = Storage.Incrementable_global_counter.get ctx + +let increment_global_counter ctx = + Storage.Incrementable_global_counter.get ctx + >>=? fun counter -> + Storage.Incrementable_global_counter.update ctx (Int32.add counter 1l) + module Parameters = Parameters_repr module Liquidity_baking = Liquidity_baking_repr diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 62de39bf9ea51b721505e936436627795e291853..cee739f59369434224a19a2df83d3fa33b4dab59 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -400,6 +400,7 @@ module Script : sig | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS + | I_INCREMENT_GLOBAL_COUNTER | T_bool | T_contract | T_int @@ -1255,6 +1256,8 @@ module Kind : sig type delegation = Delegation_kind + type global_counter_increment = Global_counter_increment + type failing_noop = Failing_noop_kind type 'a manager = @@ -1262,6 +1265,7 @@ module Kind : sig | Transaction_manager_kind : transaction manager | Origination_manager_kind : origination manager | Delegation_manager_kind : delegation manager + | Global_counter_increment_kind : global_counter_increment manager end type 'kind operation = { @@ -1351,6 +1355,7 @@ and _ manager_operation = | Delegation : Signature.Public_key_hash.t option -> Kind.delegation manager_operation + | Global_counter_increment : Kind.global_counter_increment manager_operation and counter = Z.t @@ -1499,6 +1504,9 @@ module Operation : sig val delegation_case : Kind.delegation Kind.manager case + val global_counter_increment_case : + Kind.global_counter_increment Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -1519,6 +1527,8 @@ module Operation : sig val origination_case : Kind.origination case val delegation_case : Kind.delegation case + + val global_counter_increment_case : Kind.global_counter_increment case end end @@ -1649,6 +1659,10 @@ val get_deposits : context -> Tez.t Signature.Public_key_hash.Map.t val description : context Storage_description.t +val global_counter : context -> int32 tzresult Lwt.t + +val increment_global_counter : context -> (context, error trace) result Lwt.t + module Parameters : sig type bootstrap_account = { public_key_hash : public_key_hash; diff --git a/src/proto_alpha/lib_protocol/alpha_services.ml b/src/proto_alpha/lib_protocol/alpha_services.ml index f2b23f7b61bb002e3479df77ab8335220179a62a..d8e5394f52649ce117ee1526dd61b73047f9079d 100644 --- a/src/proto_alpha/lib_protocol/alpha_services.ml +++ b/src/proto_alpha/lib_protocol/alpha_services.ml @@ -28,6 +28,24 @@ open Alpha_context let custom_root = RPC_path.open_root +module Global_variables = struct + module S = struct + let get = + RPC_service.get_service + ~description:"Get global counter" + ~query:RPC_query.empty + ~output:Data_encoding.int32 + RPC_path.(custom_root / "context" / "global-counter") + end + + let register () = + let open Services_registration in + register0 S.get (fun ctxt () () -> Alpha_context.global_counter ctxt) + + let get_global_counter ctxt block = + RPC_context.make_call0 S.get ctxt block () +end + module Seed = struct module S = struct open Data_encoding @@ -128,6 +146,7 @@ module Liquidity_baking = struct end let register () = + Global_variables.register () ; Contract.register () ; Constants.register () ; Delegate.register () ; diff --git a/src/proto_alpha/lib_protocol/alpha_services.mli b/src/proto_alpha/lib_protocol/alpha_services.mli index 2a44c99e1c4826020811c8ff0b3743e30ee1b147..6241bb2063663c89b82cdbcee9e9d907eb71e3dd 100644 --- a/src/proto_alpha/lib_protocol/alpha_services.mli +++ b/src/proto_alpha/lib_protocol/alpha_services.mli @@ -50,4 +50,9 @@ module Liquidity_baking : sig Alpha_context.Contract.t shell_tzresult Lwt.t end +module Global_variables : sig + val get_global_counter : + 'a #RPC_context.simple -> 'a -> unit -> int32 shell_tzresult Lwt.t +end + val register : unit -> unit diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 91235021599754e080656d17aa86f01e41eb48a7..b653d910ce61cbf40956853a3d1e3a5ffda40c83 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -748,6 +748,13 @@ let apply_manager_operation_content : Delegation_result {consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt}, [] ) + | Global_counter_increment -> + Alpha_context.increment_global_counter ctxt + >>=? fun ctxt -> + return + ( ctxt, + Global_counter_increment_result {consumed_gas = Gas.Arith.zero}, + [] ) type success_or_failure = Success of context | Failure diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index da0867bd95e9c0f9ff3dad677166808e778a5021..015ca87f0a08f764ce9b379d9ba08fd88949e27b 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -75,6 +75,10 @@ type _ successful_manager_operation_result = consumed_gas : Gas.Arith.fp; } -> Kind.delegation successful_manager_operation_result + | Global_counter_increment_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.global_counter_increment successful_manager_operation_result let migration_origination_result_to_successful_manager_operation_result ({ balance_updates; @@ -391,6 +395,30 @@ module Manager_result = struct ~inj:(fun (consumed_gas, consumed_milligas) -> assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; Delegation_result {consumed_gas = consumed_milligas}) + + let global_counter_increment_case = + make + ~op_case: + Operation.Encoding.Manager_operations.global_counter_increment_case + ~encoding: + Data_encoding.( + obj1 (dft "consumed_gas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~iselect:(function + | Internal_operation_result + (({operation = Global_counter_increment; _} as op), res) -> + Some (op, res) + | _ -> + None) + ~select:(function + | Successful_manager_result (Global_counter_increment_result _ as op) + -> + Some op + | _ -> + None) + ~kind:Kind.Global_counter_increment_kind + ~proj:(function + | Global_counter_increment_result {consumed_gas} -> consumed_gas) + ~inj:(fun consumed_gas -> Global_counter_increment_result {consumed_gas}) end let internal_operation_result_encoding : @@ -424,7 +452,8 @@ let internal_operation_result_encoding : [ make Manager_result.reveal_case; make Manager_result.transaction_case; make Manager_result.origination_case; - make Manager_result.delegation_case ] + make Manager_result.delegation_case; + make Manager_result.global_counter_increment_case ] let successful_manager_operation_result_encoding : packed_successful_manager_operation_result Data_encoding.t = @@ -450,7 +479,8 @@ let successful_manager_operation_result_encoding : [ make Manager_result.reveal_case; make Manager_result.transaction_case; make Manager_result.origination_case; - make Manager_result.delegation_case ] + make Manager_result.delegation_case; + make Manager_result.global_counter_increment_case ] type 'kind contents_result = | Endorsement_result : { @@ -513,6 +543,10 @@ let equal_manager_kind : Some Eq | (Kind.Delegation_manager_kind, _) -> None + | (Kind.Global_counter_increment_kind, Kind.Global_counter_increment_kind) -> + Some Eq + | (Kind.Global_counter_increment_kind, _) -> + None module Encoding = struct type 'kind case = @@ -853,6 +887,19 @@ module Encoding = struct Some (op, res) | _ -> None) + + let[@coq_axiom_with_reason "gadt"] global_counter_increment_case = + make_manager_case + Operation.Encoding.global_counter_increment_case + Manager_result.global_counter_increment_case + (function + | Contents_and_result + ( ( Manager_operation {operation = Global_counter_increment; _} as + op ), + res ) -> + Some (op, res) + | _ -> + None) end let contents_result_encoding = @@ -884,7 +931,8 @@ let contents_result_encoding = make reveal_case; make transaction_case; make origination_case; - make delegation_case ] + make delegation_case; + make global_counter_increment_case ] let contents_and_result_encoding = let open Encoding in @@ -920,7 +968,8 @@ let contents_and_result_encoding = make reveal_case; make transaction_case; make origination_case; - make delegation_case ] + make delegation_case; + make global_counter_increment_case ] type 'kind contents_result_list = | Single_result : 'kind contents_result -> 'kind contents_result_list @@ -1151,6 +1200,30 @@ let kind_equal : Some Eq | (Manager_operation {operation = Delegation _; _}, _) -> None + | ( Manager_operation {operation = Global_counter_increment; _}, + Manager_operation_result + {operation_result = Applied (Global_counter_increment_result _); _} ) + -> + Some Eq + | ( Manager_operation {operation = Global_counter_increment; _}, + Manager_operation_result + { operation_result = Backtracked (Global_counter_increment_result _, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Global_counter_increment; _}, + Manager_operation_result + { operation_result = + Failed (Alpha_context.Kind.Global_counter_increment_kind, _); + _ } ) -> + Some Eq + | ( Manager_operation {operation = Global_counter_increment; _}, + Manager_operation_result + { operation_result = + Skipped Alpha_context.Kind.Global_counter_increment_kind; + _ } ) -> + Some Eq + | (Manager_operation {operation = Global_counter_increment; _}, _) -> + None let rec kind_equal_list : type kind kind2. diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index fb05987c7edd10e45c6bfe7bea861c8512adbe4e..3dc6170f149f8f1429465ce16c00c9d7693365c5 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -126,6 +126,10 @@ and _ successful_manager_operation_result = consumed_gas : Gas.Arith.fp; } -> Kind.delegation successful_manager_operation_result + | Global_counter_increment_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.global_counter_increment successful_manager_operation_result and packed_successful_manager_operation_result = | Successful_manager_result : diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 626405dbe651ff5de3cbf198a133247e46fe141c..ebdbd9d6b7c67395c76a4681813e9e3526ab8035 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -63,6 +63,8 @@ let prepare_first_block ctxt ~typecheck ~level ~timestamp ~fitness = >>=? fun ctxt -> Contract_storage.init ctxt >>=? fun ctxt -> + Storage.Incrementable_global_counter.init ctxt 0l + >>=? fun ctxt -> Bootstrap_storage.init ctxt ~typecheck diff --git a/src/proto_alpha/lib_protocol/michelson_v1_gas.ml b/src/proto_alpha/lib_protocol/michelson_v1_gas.ml index f65d2fc1a9577c154b11554db67e5d505c0fd3e6..5ed5082497914fe2425cb44027b0bae3455e6afe 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_gas.ml +++ b/src/proto_alpha/lib_protocol/michelson_v1_gas.ml @@ -1368,6 +1368,9 @@ module Cost_of = struct (int_bytes ticket_a.amount) (int_bytes ticket_b.amount)) + (* TODO: Joel - how to calculate gas cost? *) + let increment_global_counter = S.safe_int 100 + (* Continuations *) module Control = struct let nil = atomic_step_cost cost_N_KNil diff --git a/src/proto_alpha/lib_protocol/michelson_v1_gas.mli b/src/proto_alpha/lib_protocol/michelson_v1_gas.mli index 30ef4ff903effea173a0cbe826cfdf8457b60082..04fa5cb7b9e52b72b3ea1956ab43872d2a194aed 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_gas.mli +++ b/src/proto_alpha/lib_protocol/michelson_v1_gas.mli @@ -391,6 +391,8 @@ module Cost_of : sig 'a Script_typed_ir.ticket -> Gas.cost + val increment_global_counter : Gas.cost + module Control : sig val nil : Gas.cost diff --git a/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml b/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml index 2231590b94c2ad98e61c19e67f4ab251734b2e97..1f86fcc1f07b3e3ea7b02c5875c01c0b00e9870d 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml +++ b/src/proto_alpha/lib_protocol/michelson_v1_primitives.ml @@ -146,6 +146,7 @@ type prim = | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS + | I_INCREMENT_GLOBAL_COUNTER | T_bool | T_contract | T_int @@ -243,6 +244,7 @@ let namespace = function | I_ISNAT | I_ITER | I_JOIN_TICKETS + | I_INCREMENT_GLOBAL_COUNTER | I_KECCAK | I_LAMBDA | I_LE @@ -567,6 +569,8 @@ let string_of_prim = function "SPLIT_TICKET" | I_JOIN_TICKETS -> "JOIN_TICKETS" + | I_INCREMENT_GLOBAL_COUNTER -> + "INCREMENT_GLOBAL_COUNTER" | T_bool -> "bool" | T_contract -> @@ -851,6 +855,8 @@ let prim_of_string = function ok I_SPLIT_TICKET | "JOIN_TICKETS" -> ok I_JOIN_TICKETS + | "INCREMENT_GLOBAL_COUNTER" -> + ok I_INCREMENT_GLOBAL_COUNTER | "bool" -> ok T_bool | "contract" -> @@ -1113,6 +1119,7 @@ let prim_encoding = ("READ_TICKET", I_READ_TICKET); ("SPLIT_TICKET", I_SPLIT_TICKET); ("JOIN_TICKETS", I_JOIN_TICKETS); + ("INCREMENT_GLOBAL_COUNTER", I_INCREMENT_GLOBAL_COUNTER); ("GET_AND_UPDATE", I_GET_AND_UPDATE) (* 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 0b02822f021c92ac02a09e479bd079e6c1161c47..861855dd0ccec2805f6de94b998205c8d2d9e66d 100644 --- a/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli +++ b/src/proto_alpha/lib_protocol/michelson_v1_primitives.mli @@ -145,6 +145,7 @@ type prim = | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS + | I_INCREMENT_GLOBAL_COUNTER | T_bool | T_contract | T_int diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 5666100d52f221b02182557503cfec1ba8dd3ac2..be42cd5dbd45d41d7cd55fdc28f62413787bf78f 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -50,6 +50,8 @@ module Kind = struct type delegation = Delegation_kind + type global_counter_increment = Global_counter_increment + type failing_noop = Failing_noop_kind type 'a manager = @@ -57,6 +59,7 @@ module Kind = struct | Transaction_manager_kind : transaction manager | Origination_manager_kind : origination manager | Delegation_manager_kind : delegation manager + | Global_counter_increment_kind : global_counter_increment manager end type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} @@ -150,6 +153,7 @@ and _ manager_operation = | Delegation : Signature.Public_key_hash.t option -> Kind.delegation manager_operation + | Global_counter_increment : Kind.global_counter_increment manager_operation and counter = Z.t @@ -163,6 +167,8 @@ let manager_kind : type kind. kind manager_operation -> kind Kind.manager = Kind.Origination_manager_kind | Delegation _ -> Kind.Delegation_manager_kind + | Global_counter_increment -> + Kind.Global_counter_increment_kind type 'kind internal_operation = { source : Contract_repr.contract; @@ -358,6 +364,19 @@ module Encoding = struct inj = (fun key -> Delegation key); } + let[@coq_axiom_with_reason "gadt"] global_counter_increment_case = + MCase + { + tag = 4; + name = "global_counter_increment"; + encoding = unit; + select = + (function + | Manager (Global_counter_increment as op) -> Some op | _ -> None); + proj = (function Global_counter_increment -> ()); + inj = (fun _ -> Global_counter_increment); + } + let encoding = let make (MCase {tag; name; encoding; select; proj; inj}) = case @@ -373,7 +392,8 @@ module Encoding = struct [ make reveal_case; make transaction_case; make origination_case; - make delegation_case ] + make delegation_case; + make global_counter_increment_case ] end type 'b case = @@ -629,6 +649,9 @@ module Encoding = struct let delegation_case = make_manager_case 110 Manager_operations.delegation_case + let global_counter_increment_case = + make_manager_case 111 Manager_operations.global_counter_increment_case + let contents_encoding = let make (Case {tag; name; encoding; select; proj; inj}) = case @@ -652,6 +675,7 @@ module Encoding = struct make transaction_case; make origination_case; make delegation_case; + make global_counter_increment_case; make failing_noop_case ] let contents_list_encoding = @@ -836,6 +860,10 @@ let equal_manager_operation_kind : Some Eq | (Delegation _, _) -> None + | (Global_counter_increment, Global_counter_increment) -> + Some Eq + | (Global_counter_increment, _) -> + None let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option = diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 20b3fb7ce493698c131bd00c82823a398c82f941..65d3746ab721eedd986dfc4d3f4ac23eef0f7bea 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -52,11 +52,14 @@ module Kind : sig type failing_noop = Failing_noop_kind + type global_counter_increment = Global_counter_increment + type 'a manager = | Reveal_manager_kind : reveal manager | Transaction_manager_kind : transaction manager | Origination_manager_kind : origination manager | Delegation_manager_kind : delegation manager + | Global_counter_increment_kind : global_counter_increment manager end type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} @@ -150,6 +153,7 @@ and _ manager_operation = | Delegation : Signature.Public_key_hash.t option -> Kind.delegation manager_operation + | Global_counter_increment : Kind.global_counter_increment manager_operation and counter = Z.t @@ -258,6 +262,9 @@ module Encoding : sig val delegation_case : Kind.delegation Kind.manager case + val global_counter_increment_case : + Kind.global_counter_increment Kind.manager case + module Manager_operations : sig type 'b case = | MCase : { @@ -277,5 +284,7 @@ module Encoding : sig val origination_case : Kind.origination case val delegation_case : Kind.delegation case + + val global_counter_increment_case : Kind.global_counter_increment case end end diff --git a/src/proto_alpha/lib_protocol/script_interpreter.ml b/src/proto_alpha/lib_protocol/script_interpreter.ml index ac2d7e89c2996aa44cf18e2cd7f2250d485ba851..68bbdb512d50174ba98db92b30bc238ee12ed685 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter.ml @@ -1384,7 +1384,18 @@ and step : type a s b t r f. (a, s, b, t, r, f) step_type = } else None in - (step [@ocaml.tailcall]) g gas k ks result stack ) + (step [@ocaml.tailcall]) g gas k ks result stack + | IIncrement_global_counter (_, k) -> + let operation = Global_counter_increment in + let ctxt = update_context gas ctxt in + fresh_internal_nonce ctxt + >>?= fun (ctxt, nonce) -> + let res = + (Internal_operation {source = sc.self; operation; nonce}, None) + in + let gas = update_local_gas_counter ctxt in + let ctxt = outdated ctxt in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks res (accu, stack) ) (* diff --git a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml index c51d6bac65149cca6a81fc174304498202450009..83a9eb70eadae99656c4cc2bc8050a94ce611a05 100644 --- a/src/proto_alpha/lib_protocol/script_interpreter_defs.ml +++ b/src/proto_alpha/lib_protocol/script_interpreter_defs.ml @@ -438,6 +438,8 @@ let cost_of_instr : type a s r f. (a, s, r, f) kinstr -> a -> s -> Gas.cost = Interp_costs.read_ticket | ILog _ -> Gas.free + | IIncrement_global_counter _ -> + Interp_costs.increment_global_counter [@@ocaml.inline always] let cost_of_control : type a s r f. (a, s, r, f) continuation -> Gas.cost = diff --git a/src/proto_alpha/lib_protocol/script_ir_translator.ml b/src/proto_alpha/lib_protocol/script_ir_translator.ml index a5a261be9394fb96d8d759485db81cd332cfbada..d5c222971914ccf9793f906f3dd3a88ad23c802a 100644 --- a/src/proto_alpha/lib_protocol/script_ir_translator.ml +++ b/src/proto_alpha/lib_protocol/script_ir_translator.ml @@ -5889,6 +5889,14 @@ and parse_instr : typed ctxt 0 loc instr stack | _ -> (* TODO: fix injectivity of types *) assert false ) + | (Prim (loc, I_INCREMENT_GLOBAL_COUNTER, [], annot), rest) -> + parse_var_annot loc annot + >>?= fun annot -> + let instr = + {apply = (fun kinfo k -> IIncrement_global_counter (kinfo, k))} + in + let stack = Item_t (Operation_t None, rest, annot) in + typed ctxt 0 loc instr stack (* Primitive parsing errors *) | ( Prim ( loc, diff --git a/src/proto_alpha/lib_protocol/script_typed_ir.ml b/src/proto_alpha/lib_protocol/script_typed_ir.ml index f71dcd6bd3252b55f23dcd10f680c473256df137..e0a78cb27dc55acf6cb75dd2dfa209cec27a101a 100644 --- a/src/proto_alpha/lib_protocol/script_typed_ir.ml +++ b/src/proto_alpha/lib_protocol/script_typed_ir.ml @@ -923,6 +923,9 @@ and ('before_top, 'before, 'result_top, 'result) kinstr = * 'a comparable_ty * ('a ticket option, 's, 'r, 'f) kinstr -> ('a ticket * 'a ticket, 's, 'r, 'f) kinstr + | IIncrement_global_counter : + ('a, 's) kinfo * (operation, 'a * 's, 'r, 'f) kinstr + -> ('a, 's, 'r, 'f) kinstr (* Internal control instructions @@ -1571,6 +1574,8 @@ let kinfo_of_kinstr : type a s b f. (a, s, b, f) kinstr -> (a, s) kinfo = kinfo | ILog (kinfo, _, _, _) -> kinfo + | IIncrement_global_counter (kinfo, _) -> + kinfo type kinstr_rewritek = { apply : 'b 'u 'r 'f. ('b, 'u, 'r, 'f) kinstr -> ('b, 'u, 'r, 'f) kinstr; @@ -1906,3 +1911,5 @@ let kinstr_rewritek : IHalt kinfo | ILog (kinfo, event, logger, k) -> ILog (kinfo, event, logger, k) + | IIncrement_global_counter (kinfo, k) -> + IIncrement_global_counter (kinfo, k) diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index ae2ab52f0ca2e4cec103b2ae316db10c5497b7cb..660bbb29d4889b4c6fdf99f17022fea427284c03 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -82,6 +82,13 @@ module Make_index (H : Storage_description.INDEX) : let args = Storage_description.One {rpc_arg; encoding; compare} end +module Incrementable_global_counter = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["global_counter_incrementable"] + end) + (Int32) + module Block_priority = Make_single_data_storage (Registered) (Raw_context) (struct diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index eef475d28b1126f38d1bbbd4fcce08ecb7383934..c66d20ec4eeebf8ca735efd4b55cb1597935ffa7 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -36,6 +36,14 @@ open Storage_sigs +module Incrementable_global_counter : sig + val get : Raw_context.t -> int32 tzresult Lwt.t + + val update : Raw_context.t -> int32 -> Raw_context.t tzresult Lwt.t + + val init : Raw_context.t -> int32 -> Raw_context.t tzresult Lwt.t +end + module Block_priority : sig val get : Raw_context.t -> int tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 5d6bcadd43804b04f378254c94c6c36d1527e463..22f0ef95537afe65c9bb3a2a2f9c9c0013e3d669 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -611,6 +611,7 @@ let bake_n_with_all_balance_updates ?policy ?liquidity_baking_escape_vote n b = let open Apply_results in function | Successful_manager_result (Reveal_result _) + | Successful_manager_result (Global_counter_increment_result _) | Successful_manager_result (Delegation_result _) -> balance_updates_rev | Successful_manager_result @@ -638,6 +639,7 @@ let bake_n_with_origination_results ?policy n b = function | Successful_manager_result (Reveal_result _) | Successful_manager_result (Delegation_result _) + | Successful_manager_result (Global_counter_increment_result _) | Successful_manager_result (Transaction_result _) -> origination_results_rev | Successful_manager_result (Origination_result x) -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index fef9d7916f369661f2f51593712bcf77b7bdad97..540504829c48f785a28067d3e8284d38aa3a7bd2 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -181,6 +181,9 @@ let get_liquidity_baking_subsidy ctxt = let get_liquidity_baking_cpmm_address ctxt = Alpha_services.Liquidity_baking.get_cpmm_address rpc_ctxt ctxt +let get_global_counter ctxt = + Alpha_services.Global_variables.get_global_counter rpc_ctxt ctxt () + (* Voting *) module Vote = struct diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index daa7b51b42284d9b05c7c2359684c4b32031b50c..0dd69d6ad793f1bbfb3ebafc1ace09daec10bcb0 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -65,6 +65,8 @@ val get_endorsing_reward : val get_liquidity_baking_subsidy : t -> Tez.t tzresult Lwt.t +val get_global_counter : t -> int32 tzresult Lwt.t + val get_liquidity_baking_cpmm_address : t -> Contract.t tzresult Lwt.t module Vote : sig diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 2b982650af559b386b5996e12f1aec45a2e8bbc4..ddec217207e82ec2ceafc4083f3e21fe19fb3a98 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -330,6 +330,20 @@ let transaction ?counter ?fee ?gas_limit ?storage_limit Context.Contract.manager ctxt src >|=? fun account -> sign account.sk ctxt sop +let increment_global_counter ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) = + manager_operation + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + Global_counter_increment + >>=? fun sop -> + Context.Contract.manager ctxt src + >|=? fun account -> sign account.sk ctxt sop + let delegation ?fee ctxt source dst = let top = Delegation dst in manager_operation diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index 6d569d47eb7039c5d980e76c4b3016ff7c690097..a77d5a525468352381fca44257e8fadf939cc174 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -139,3 +139,12 @@ val ballot : val dummy_script : Script.t val dummy_script_cost : Test_tez.Tez.t + +val increment_global_counter : + ?counter:counter -> + ?fee:Tez.t -> + ?gas_limit:Fixed_point_repr.integral_tag Gas.Arith.t -> + ?storage_limit:counter -> + Context.t -> + Contract.t -> + (packed_operation, error trace) result Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/main.ml b/src/proto_alpha/lib_protocol/test/main.ml index f5aa6fb23b6c1a43d72dab6d7c6f9f23dc1ac34b..95e49ac3e418f11107763a956295c525ee026ec6 100644 --- a/src/proto_alpha/lib_protocol/test/main.ml +++ b/src/proto_alpha/lib_protocol/test/main.ml @@ -63,5 +63,6 @@ let () = ("constants", Test_constants.tests); ("level module", Test_level_module.tests); ("liquidity baking", Test_liquidity_baking.tests); - ("temp big maps", Test_temp_big_maps.tests) ] + ("temp big maps", Test_temp_big_maps.tests); + ("test_global_counter", Test_global_counter.tests) ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/test_global_counter.ml b/src/proto_alpha/lib_protocol/test/test_global_counter.ml new file mode 100644 index 0000000000000000000000000000000000000000..eab9bcfd58af9c9368c7a004457d0d3ddfb164ac --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/test_global_counter.ml @@ -0,0 +1,102 @@ +module AC = Protocol.Alpha_context + +let register_contract () = + Context.init 1 + >>=? function + | (block, [contract]) -> + return (block, contract) + | _ -> + Error_monad.failwith "Expected single contract" + +let make_contract ~code ~originator ~amount ~block = + Incremental.begin_construction block + >>=? fun block -> + let code = AC.Script.lazy_expr @@ Expr.from_string code in + let credit = AC.Tez.of_mutez_exn (Int64.of_int amount) in + let script = Op.{dummy_script with code} in + Op.origination (I block) originator ~script ~credit + >>=? fun (op, originated_contract) -> + Incremental.add_operation block op + >>=? fun block -> + Incremental.finalize_block block + |> Lwt_result.map (fun block -> (block, originated_contract)) + +let transfer block ~sender ~recipient ~amount ~entrypoint = + Incremental.begin_construction block + >>=? fun block -> + Op.transaction + (I block) + ~entrypoint + ~fee:AC.Tez.zero + sender + recipient + (AC.Tez.of_mutez_exn amount) + >>=? Incremental.add_operation block + >>=? Incremental.finalize_block + +let call_contract_with_increment_global_counater () = + register_contract () + >>=? fun (block, originator) -> + let code = + {| + {parameter unit; + storage unit; + code { + CAR; + NIL operation; + INCREMENT_GLOBAL_COUNTER; + CONS; PAIR; + } + } + |} + in + make_contract ~code ~originator ~amount:0 ~block + >>=? fun (block, recipient) -> + transfer block ~sender:originator ~recipient ~amount:0L ~entrypoint:"default" + >>=? fun block -> + Incremental.begin_construction block + >>=? fun inc -> + Context.get_global_counter (I inc) + >>=? fun n -> Assert.equal_int32 ~loc:__LOC__ 1l n + +let global_counter_initially_zero () = + register_contract () + >>=? fun (block, _) -> + Incremental.begin_construction block + >>=? fun inc -> + Context.get_global_counter (I inc) + >>=? fun n -> Assert.equal_int32 ~loc:__LOC__ 0l n + +let repeat_increment_counter block contract n = + let gas_limit = AC.Gas.Arith.integral_of_int_exn 1000 in + let rec increment_n n inc = + if n <= 0 then return inc + else + Op.increment_global_counter ~gas_limit (I inc) contract + >>=? Incremental.add_operation inc + >>=? increment_n (n - 1) + in + Incremental.begin_construction block >>=? increment_n n + +let increment_global_counter () = + let n = 3 in + register_contract () + >>=? fun (block, contract) -> + repeat_increment_counter block contract n + >>=? fun inc -> + Context.get_global_counter (I inc) + >>=? fun count -> Assert.equal_int32 ~loc:__LOC__ count (Int32.of_int n) + +let tests = + [ Test_services.tztest + "Global counter is initially zero" + `Quick + global_counter_initially_zero; + Test_services.tztest + "Increment global counter and check value" + `Quick + increment_global_counter; + Test_services.tztest + "Call contract with increment-global-counter instruction" + `Quick + call_contract_with_increment_global_counater ] diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index d8822ad07dd9d706390fe1eb528acf5c81e64327..646ab952c96f44f0df7910d8c8a5da572b3866a1 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -428,6 +428,15 @@ let withdraw_delegate ?node ?wait ~src client = let spawn_get_balance_for ?node ~account client = spawn_command ?node client ["get"; "balance"; "for"; account] +let spawn_get_global_counter ?node client = + spawn_command ?node client ["get"; "global-counter"] + +let spawn_increment_global_counter ?node ~gas_limit ~account client = + spawn_command + ?node + client + ["increment-global-counter"; account; "--gas-limit"; gas_limit] + let get_balance_for ?node ~account client = let extract_balance (client_output : string) : float = match client_output =~* rex "(\\d+(?:\\.\\d+)?) \u{A729}" with @@ -441,6 +450,16 @@ let get_balance_for ?node ~account client = and* output = Lwt_io.read (Process.stdout process) in return @@ extract_balance output +let get_global_counter ?node client = + let process = spawn_get_global_counter ?node client in + let* () = Process.check process + and* output = Lwt_io.read (Process.stdout process) in + return @@ int_of_string @@ String.trim output + +let increment_global_counter ?node ~account ~gas_limit client = + spawn_increment_global_counter ?node ~account ~gas_limit client + |> Process.check + let spawn_create_mockup ?(sync_mode = Synchronous) ?constants ~protocol client = let cmd = diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 9ac032932095b4e4e73f7ea09e1f68a353ad0158..563d86c4283e03c337de714034f1d750a9e0e685 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -324,9 +324,14 @@ val spawn_withdraw_delegate : (** Run [tezos-client get balance for]. *) val get_balance_for : ?node:Node.t -> account:string -> t -> float Lwt.t +val get_global_counter : ?node:Node.t -> t -> int Lwt.t + (** Same as [get_balance_for], but do not wait for the process to exit. *) val spawn_get_balance_for : ?node:Node.t -> account:string -> t -> Process.t +val increment_global_counter : + ?node:Node.t -> account:string -> gas_limit:string -> t -> unit Lwt.t + (** Run [tezos-client create mockup]. *) val create_mockup : ?sync_mode:mockup_sync_mode -> diff --git a/tezt/tests/contracts/proto_alpha/increment_global_counter.tz b/tezt/tests/contracts/proto_alpha/increment_global_counter.tz new file mode 100644 index 0000000000000000000000000000000000000000..8cf3b85ac4b9c329aa01c9441c4260289cdfb8ef --- /dev/null +++ b/tezt/tests/contracts/proto_alpha/increment_global_counter.tz @@ -0,0 +1,3 @@ +parameter string; +storage string; +code {CAR; NIL operation; INCREMENT_GLOBAL_COUNTER; CONS; PAIR; }; diff --git a/tezt/tests/mockup.ml b/tezt/tests/mockup.ml index ec3b965a0c2f35b00763f1445f6a64fdaf4ce34a..876f47a51e2383835af9e7a43d3bdff14f1c4940 100644 --- a/tezt/tests/mockup.ml +++ b/tezt/tests/mockup.ml @@ -508,6 +508,75 @@ let test_origination_from_unrevealed_fees = in return () +let verify_global_counter client expected = + let* n = Client.get_global_counter client in + if n <> expected then + Test.fail "Expected global counter to be %d but got %d" expected n + else return () + +let test_increment_global_counter = + Protocol.register_test + ~__FILE__ + ~title:"(Mockup) Increment global counter" + ~tags:["mockup"; "client"; "increment"; "global"; "counter"] + @@ fun protocol -> + match protocol with + | Alpha -> + let (account, _, _) = transfer_data in + let* client = Client.init_mockup ~protocol () in + let* () = verify_global_counter client 0 in + let* () = + Client.increment_global_counter ~account ~gas_limit:"1000" client + in + let* () = verify_global_counter client 1 in + let* () = + Client.increment_global_counter ~account ~gas_limit:"1000" client + in + verify_global_counter client 2 + | _ -> + return () + +let test_call_contract_with_increment_global_counter = + Protocol.register_test + ~__FILE__ + ~title:"(Mockup) Call conttract with increment global counter operation" + ~tags:["mockup"; "client"; "increment"; "global"; "counter"] + @@ fun protocol -> + match protocol with + | Alpha -> + let* client = Client.init_mockup ~protocol () in + Log.info "Originate new contract that updates the global counter" ; + let* _ = + Client.originate_contract + ~alias:"increment_global_counter" + ~amount:Tez.zero + ~src:"bootstrap1" + ~prg: + "file:./tezt/tests/contracts/proto_alpha/increment_global_counter.tz" + ~init:{|""|} + ~burn_cap:(Tez.of_int 2) + client + in + let* () = Client.bake_for ~key:"bootstrap1" client in + Log.info "Verify that the global counter is initially zero" ; + let* () = verify_global_counter client 0 in + Log.info "Call the contract for incrementing the counter" ; + let* () = + Client.transfer + ~amount:Tez.zero + ~giver:"bootstrap1" + ~receiver:"increment_global_counter" + ~arg:{|"Hello"|} + ~burn_cap:(Tez.of_int 1) + ~gas_limit:10_000 + client + in + let* () = Client.bake_for ~key:"bootstrap1" client in + Log.info "Verify that the counter has been incremented" ; + verify_global_counter client 1 + | _ -> + return () + let register ~protocols = test_rpc_list ~protocols ; test_same_transfer_twice ~protocols ; @@ -516,7 +585,9 @@ let register ~protocols = test_simple_baking_event ~protocols ; test_multiple_baking ~protocols ; test_rpc_header_shell ~protocols ; - test_origination_from_unrevealed_fees ~protocols + test_origination_from_unrevealed_fees ~protocols ; + test_call_contract_with_increment_global_counter ~protocols ; + test_increment_global_counter ~protocols let register_constant_migration ~migrate_from ~migrate_to = test_migration_constants ~migrate_from ~migrate_to