From 65efc7d49ca3ecfabd068864baa747a88d7559c4 Mon Sep 17 00:00:00 2001 From: Marcin Pastudzki Date: Fri, 5 Nov 2021 11:04:56 +0100 Subject: [PATCH 1/8] Proto Alpha: Add an option to set SELF_ADDRESS for run script command. --- .../lib_client/client_proto_programs.ml | 5 + .../lib_client/client_proto_programs.mli | 1 + .../client_proto_programs_commands.ml | 13 +- src/proto_alpha/lib_plugin/plugin.ml | 113 +++++++++--------- 4 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/proto_alpha/lib_client/client_proto_programs.ml b/src/proto_alpha/lib_client/client_proto_programs.ml index 3d099a41cbc2..e6159a619e3b 100644 --- a/src/proto_alpha/lib_client/client_proto_programs.ml +++ b/src/proto_alpha/lib_client/client_proto_programs.ml @@ -143,6 +143,7 @@ type run_params = { program : Michelson_v1_parser.parsed; storage : Michelson_v1_parser.parsed; entrypoint : Entrypoint.t option; + self : Contract.t option; } let run_view (cctxt : #Protocol_client_context.rpc_context) @@ -179,6 +180,7 @@ let run (cctxt : #Protocol_client_context.rpc_context) balance; storage; entrypoint; + self; } = params in @@ -197,6 +199,7 @@ let run (cctxt : #Protocol_client_context.rpc_context) ~chain_id ~source ~payer + ~self ~now ~level @@ -210,6 +213,7 @@ let trace (cctxt : #Protocol_client_context.rpc_context) balance; storage; entrypoint; + self; } = params in @@ -228,6 +232,7 @@ let trace (cctxt : #Protocol_client_context.rpc_context) ~chain_id ~source ~payer + ~self ~now ~level diff --git a/src/proto_alpha/lib_client/client_proto_programs.mli b/src/proto_alpha/lib_client/client_proto_programs.mli index 118a167a54f0..39654254199e 100644 --- a/src/proto_alpha/lib_client/client_proto_programs.mli +++ b/src/proto_alpha/lib_client/client_proto_programs.mli @@ -58,6 +58,7 @@ type run_params = { program : Michelson_v1_parser.parsed; storage : Michelson_v1_parser.parsed; entrypoint : Entrypoint.t option; + self : Contract.t option; } val run_view : diff --git a/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml index 18048c5e4f08..671fc090ca97 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml @@ -96,6 +96,12 @@ let commands () = ~doc:"name of the payer (i.e. SOURCE) contract for the transaction" () in + let self_arg = + ContractAlias.destination_arg + ~name:"self-address" + ~doc:"address of the contract (i.e. SELF_ADDRESS) for the transaction" + () + in let balance_arg = Client_proto_args.tez_arg ~parameter:"balance" @@ -235,12 +241,13 @@ let commands () = command ~group ~desc:"Ask the node to run a script." - (args11 + (args12 trace_stack_switch amount_arg balance_arg source_arg payer_arg + self_arg no_print_source_flag run_gas_limit_arg entrypoint_arg @@ -259,6 +266,7 @@ let commands () = balance, source, payer, + self, no_print_source, gas, entrypoint, @@ -271,6 +279,7 @@ let commands () = cctxt -> let source = Option.map snd source in let payer = Option.map snd payer in + let self = Option.map snd self in Lwt.return @@ Micheline_parser.no_parsing_error program >>=? fun program -> let show_source = not no_print_source in @@ -287,6 +296,7 @@ let commands () = shared_params = {input; unparsing_mode; now; level; source; payer; gas}; entrypoint; + self; } >>= fun res -> print_trace_result cctxt ~show_source ~parsed:program res @@ -303,6 +313,7 @@ let commands () = shared_params = {input; unparsing_mode; now; level; source; payer; gas}; entrypoint; + self; } >>= fun res -> print_run_result cctxt ~show_source ~parsed:program res); command diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index f496a451dd62..2adb224666ba 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -1563,10 +1563,11 @@ module RPC = struct (req "chain_id" Chain_id.encoding) (opt "source" Contract.encoding) (opt "payer" Contract.encoding) - (opt "gas" Gas.Arith.z_integral_encoding) + (opt "self" Contract.encoding) (dft "entrypoint" Entrypoint.simple_encoding Entrypoint.default)) - (obj3 + (obj4 (opt "unparsing_mode" unparsing_mode_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) (opt "now" Script_timestamp.encoding) (opt "level" Script_int.n_encoding)) @@ -2127,6 +2128,13 @@ module RPC = struct let ctxt = Cache.Admin.future_cache_expectation ctxt ~time_in_blocks in run_operation_service ctxt () (op, chain_id) + (* A convenience type for return values of [ensure_contracts_exist] below. *) + type run_code_addresses = { + self : Contract.t; + payer : Contract.t; + source : Contract.t; + } + let register () = let originate_dummy_contract ctxt script balance = let ctxt = Origination_nonce.init ctxt Operation_hash.zero in @@ -2146,6 +2154,19 @@ module RPC = struct balance >>=? fun (ctxt, _) -> return (ctxt, dummy_contract) in + let ensure_contracts_exist ctxt script balance src_opt pay_opt self_opt = + (match self_opt with + | None -> originate_dummy_contract ctxt script balance + | Some s -> return (ctxt, s)) + >>=? fun (ctxt, self) -> + let (source, payer) = + match (src_opt, pay_opt) with + | (None, None) -> (self, self) + | (Some c, None) | (None, Some c) -> (c, c) + | (Some src, Some pay) -> (src, pay) + in + return (ctxt, {self; source; payer}) + in let script_entrypoint_type ctxt expr entrypoint = let ctxt = Gas.set_unlimited ctxt in let legacy = false in @@ -2176,24 +2197,23 @@ module RPC = struct amount, balance, chain_id, - source, - payer, - gas, + source_opt, + payer_opt, + self_opt, entrypoint ), - (unparsing_mode, now, level) ) + (unparsing_mode, gas, now, level) ) -> let unparsing_mode = Option.value ~default:Readable unparsing_mode in let storage = Script.lazy_expr storage in let code = Script.lazy_expr code in - originate_dummy_contract ctxt {storage; code} balance - >>=? fun (ctxt, dummy_contract) -> - let (source, payer) = - match (source, payer) with - | (Some source, Some payer) -> (source, payer) - | (Some source, None) -> (source, source) - | (None, Some payer) -> (payer, payer) - | (None, None) -> (dummy_contract, dummy_contract) - in + ensure_contracts_exist + ctxt + {storage; code} + balance + source_opt + payer_opt + self_opt + >>=? fun (ctxt, {self; source; payer}) -> let gas = match gas with | Some gas -> gas @@ -2212,16 +2232,7 @@ module RPC = struct in let step_constants = let open Script_interpreter in - { - source; - payer; - self = dummy_contract; - amount; - balance; - chain_id; - now; - level; - } + {source; payer; self; amount; balance; chain_id; now; level} in Script_interpreter.execute ctxt @@ -2251,24 +2262,23 @@ module RPC = struct amount, balance, chain_id, - source, - payer, - gas, + source_opt, + payer_opt, + self_opt, entrypoint ), - (unparsing_mode, now, level) ) + (unparsing_mode, gas, now, level) ) -> let unparsing_mode = Option.value ~default:Readable unparsing_mode in let storage = Script.lazy_expr storage in let code = Script.lazy_expr code in - originate_dummy_contract ctxt {storage; code} balance - >>=? fun (ctxt, dummy_contract) -> - let (source, payer) = - match (source, payer) with - | (Some source, Some payer) -> (source, payer) - | (Some source, None) -> (source, source) - | (None, Some payer) -> (payer, payer) - | (None, None) -> (dummy_contract, dummy_contract) - in + ensure_contracts_exist + ctxt + {storage; code} + balance + source_opt + payer_opt + self_opt + >>=? fun (ctxt, {self; source; payer}) -> let gas = match gas with | Some gas -> gas @@ -2287,16 +2297,7 @@ module RPC = struct in let step_constants = let open Script_interpreter in - { - source; - payer; - self = dummy_contract; - amount; - balance; - chain_id; - now; - level; - } + {source; payer; self; amount; balance; chain_id; now; level} in let module Unparsing_mode = struct let unparsing_mode = unparsing_mode @@ -2566,8 +2567,8 @@ module RPC = struct [] ) )) let run_code ?unparsing_mode ?gas ?(entrypoint = Entrypoint.default) ~script - ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~now ~level - ctxt block = + ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~self ~now + ~level ctxt block = RPC_context.make_call0 S.run_code ctxt @@ -2581,13 +2582,13 @@ module RPC = struct chain_id, source, payer, - gas, + self, entrypoint ), - (unparsing_mode, now, level) ) + (unparsing_mode, gas, now, level) ) let trace_code ?unparsing_mode ?gas ?(entrypoint = Entrypoint.default) - ~script ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~now - ~level ctxt block = + ~script ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~self + ~now ~level ctxt block = RPC_context.make_call0 S.trace_code ctxt @@ -2601,9 +2602,9 @@ module RPC = struct chain_id, source, payer, - gas, + self, entrypoint ), - (unparsing_mode, now, level) ) + (unparsing_mode, gas, now, level) ) let run_view ?gas ~contract ~entrypoint ~input ~chain_id ~now ~level ?source ?payer ~unparsing_mode ctxt block = -- GitLab From 91bb82053821bc2a5d479d0edb7a562ea7b8f757 Mon Sep 17 00:00:00 2001 From: Marcin Pastudzki Date: Mon, 6 Dec 2021 14:58:20 +0100 Subject: [PATCH 2/8] Protocol Alpha: Take existing contract's balance for run script. If --self-address was given to run script command of tezos-client and --balance WAS NOT specified, take existing contract's balance as the relevant step constant. --- .../lib_client/client_proto_args.ml | 7 ++ .../lib_client/client_proto_args.mli | 3 + .../lib_client/client_proto_programs.ml | 6 +- .../lib_client/client_proto_programs.mli | 2 +- .../client_proto_programs_commands.ml | 3 +- src/proto_alpha/lib_plugin/plugin.ml | 66 ++++++++++++------- 6 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/proto_alpha/lib_client/client_proto_args.ml b/src/proto_alpha/lib_client/client_proto_args.ml index f933269bc855..d74324344529 100644 --- a/src/proto_alpha/lib_client/client_proto_args.ml +++ b/src/proto_alpha/lib_client/client_proto_args.ml @@ -247,6 +247,13 @@ let tez_arg ~default ~parameter ~doc = ~default (tez_parameter ("--" ^ parameter)) +let tez_opt_arg ~parameter ~doc = + arg + ~long:parameter + ~placeholder:"amount" + ~doc + (tez_parameter ("--" ^ parameter)) + let tez_param ~name ~desc next = Clic.param ~name diff --git a/src/proto_alpha/lib_client/client_proto_args.mli b/src/proto_alpha/lib_client/client_proto_args.mli index 3b1a2aac0594..5ff707bf8745 100644 --- a/src/proto_alpha/lib_client/client_proto_args.mli +++ b/src/proto_alpha/lib_client/client_proto_args.mli @@ -99,6 +99,9 @@ val no_confirmation : (bool, full) Clic.arg val tez_arg : default:string -> parameter:string -> doc:string -> (Tez.t, full) Clic.arg +val tez_opt_arg : + parameter:string -> doc:string -> (Tez.t option, full) Clic.arg + val tez_param : name:string -> desc:string -> diff --git a/src/proto_alpha/lib_client/client_proto_programs.ml b/src/proto_alpha/lib_client/client_proto_programs.ml index e6159a619e3b..518aa3c40677 100644 --- a/src/proto_alpha/lib_client/client_proto_programs.ml +++ b/src/proto_alpha/lib_client/client_proto_programs.ml @@ -139,7 +139,7 @@ type run_view_params = { type run_params = { shared_params : simulation_params; amount : Tez.t option; - balance : Tez.t; + balance : Tez.t option; program : Michelson_v1_parser.parsed; storage : Michelson_v1_parser.parsed; entrypoint : Entrypoint.t option; @@ -195,7 +195,7 @@ let run (cctxt : #Protocol_client_context.rpc_context) ~storage:storage.expanded ~input:input.expanded ~amount - ~balance + ?balance ~chain_id ~source ~payer @@ -228,7 +228,7 @@ let trace (cctxt : #Protocol_client_context.rpc_context) ~storage:storage.expanded ~input:input.expanded ~amount - ~balance + ?balance ~chain_id ~source ~payer diff --git a/src/proto_alpha/lib_client/client_proto_programs.mli b/src/proto_alpha/lib_client/client_proto_programs.mli index 39654254199e..a2e74ec62080 100644 --- a/src/proto_alpha/lib_client/client_proto_programs.mli +++ b/src/proto_alpha/lib_client/client_proto_programs.mli @@ -54,7 +54,7 @@ type run_view_params = { type run_params = { shared_params : simulation_params; amount : Tez.t option; - balance : Tez.t; + balance : Tez.t option; program : Michelson_v1_parser.parsed; storage : Michelson_v1_parser.parsed; entrypoint : Entrypoint.t option; diff --git a/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml index 671fc090ca97..737b858c36e7 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_programs_commands.ml @@ -103,10 +103,9 @@ let commands () = () in let balance_arg = - Client_proto_args.tez_arg + Client_proto_args.tez_opt_arg ~parameter:"balance" ~doc:"balance of run contract in \xEA\x9C\xA9" - ~default:"4_000_000" in let now_arg = Client_proto_args.now_arg in let level_arg = Client_proto_args.level_arg in diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 2adb224666ba..a1d898e12210 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -1559,7 +1559,7 @@ module RPC = struct (req "storage" Script.expr_encoding) (req "input" Script.expr_encoding) (req "amount" Tez.encoding) - (req "balance" Tez.encoding) + (opt "balance" Tez.encoding) (req "chain_id" Chain_id.encoding) (opt "source" Contract.encoding) (opt "payer" Contract.encoding) @@ -2128,13 +2128,21 @@ module RPC = struct let ctxt = Cache.Admin.future_cache_expectation ctxt ~time_in_blocks in run_operation_service ctxt () (op, chain_id) + let default_from_context ctxt get = function + | None -> get ctxt + | Some x -> return x + (* A convenience type for return values of [ensure_contracts_exist] below. *) - type run_code_addresses = { + type run_code_config = { + balance : Tez.t; self : Contract.t; payer : Contract.t; source : Contract.t; } + (* 4_000_000 ꜩ *) + let default_balance = Tez.of_mutez_exn 4_000_000_000_000L + let register () = let originate_dummy_contract ctxt script balance = let ctxt = Origination_nonce.init ctxt Operation_hash.zero in @@ -2154,18 +2162,26 @@ module RPC = struct balance >>=? fun (ctxt, _) -> return (ctxt, dummy_contract) in - let ensure_contracts_exist ctxt script balance src_opt pay_opt self_opt = + let configure_contracts ctxt script balance ~src_opt ~pay_opt ~self_opt = (match self_opt with - | None -> originate_dummy_contract ctxt script balance - | Some s -> return (ctxt, s)) - >>=? fun (ctxt, self) -> + | None -> + let balance = Option.value ~default:default_balance balance in + originate_dummy_contract ctxt script balance + >>=? fun (ctxt, addr) -> return (ctxt, addr, balance) + | Some addr -> + default_from_context + ctxt + (fun c -> Contract.get_balance c addr) + balance + >>=? fun bal -> return (ctxt, addr, bal)) + >>=? fun (ctxt, self, balance) -> let (source, payer) = match (src_opt, pay_opt) with | (None, None) -> (self, self) | (Some c, None) | (None, Some c) -> (c, c) | (Some src, Some pay) -> (src, pay) in - return (ctxt, {self; source; payer}) + return (ctxt, {balance; self; source; payer}) in let script_entrypoint_type ctxt expr entrypoint = let ctxt = Gas.set_unlimited ctxt in @@ -2197,8 +2213,8 @@ module RPC = struct amount, balance, chain_id, - source_opt, - payer_opt, + src_opt, + pay_opt, self_opt, entrypoint ), (unparsing_mode, gas, now, level) ) @@ -2206,14 +2222,14 @@ module RPC = struct let unparsing_mode = Option.value ~default:Readable unparsing_mode in let storage = Script.lazy_expr storage in let code = Script.lazy_expr code in - ensure_contracts_exist + configure_contracts ctxt {storage; code} balance - source_opt - payer_opt - self_opt - >>=? fun (ctxt, {self; source; payer}) -> + ~src_opt + ~pay_opt + ~self_opt + >>=? fun (ctxt, {self; source; payer; balance}) -> let gas = match gas with | Some gas -> gas @@ -2262,8 +2278,8 @@ module RPC = struct amount, balance, chain_id, - source_opt, - payer_opt, + src_opt, + pay_opt, self_opt, entrypoint ), (unparsing_mode, gas, now, level) ) @@ -2271,14 +2287,14 @@ module RPC = struct let unparsing_mode = Option.value ~default:Readable unparsing_mode in let storage = Script.lazy_expr storage in let code = Script.lazy_expr code in - ensure_contracts_exist + configure_contracts ctxt {storage; code} balance - source_opt - payer_opt - self_opt - >>=? fun (ctxt, {self; source; payer}) -> + ~src_opt + ~pay_opt + ~self_opt + >>=? fun (ctxt, {self; source; payer; balance}) -> let gas = match gas with | Some gas -> gas @@ -2566,9 +2582,9 @@ module RPC = struct map [] ) )) - let run_code ?unparsing_mode ?gas ?(entrypoint = Entrypoint.default) ~script - ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~self ~now - ~level ctxt block = + let run_code ?unparsing_mode ?gas ?(entrypoint = Entrypoint.default) + ?balance ~script ~storage ~input ~amount ~chain_id ~source ~payer ~self + ~now ~level ctxt block = RPC_context.make_call0 S.run_code ctxt @@ -2587,7 +2603,7 @@ module RPC = struct (unparsing_mode, gas, now, level) ) let trace_code ?unparsing_mode ?gas ?(entrypoint = Entrypoint.default) - ~script ~storage ~input ~amount ~balance ~chain_id ~source ~payer ~self + ?balance ~script ~storage ~input ~amount ~chain_id ~source ~payer ~self ~now ~level ctxt block = RPC_context.make_call0 S.trace_code -- GitLab From edd3c3d1e52d9ca8d1df77c624be781052ec8098 Mon Sep 17 00:00:00 2001 From: Marcin Pastudzki Date: Fri, 7 Jan 2022 16:03:48 +0100 Subject: [PATCH 3/8] Tezt: Rename ~src argument to run_script to ~prg. Firstly, this is consistent with originate_contract, which also has ~prg argument rather than ~src. Secondly, run_script also has --source parameter, which would be confusing to add if ~src was already present. --- tezt/lib_tezos/client.ml | 8 ++++---- tezt/lib_tezos/client.mli | 4 ++-- tezt/tests/mockup.ml | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 46f02e10e110..514a82cc3704 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -890,15 +890,15 @@ let stresstest ?endpoint ?source_aliases ?source_pkhs ?source_accounts ?seed client |> Process.check -let spawn_run_script ?hooks ~src ~storage ~input client = +let spawn_run_script ?hooks ~prg ~storage ~input client = spawn_command ?hooks client - ["run"; "script"; src; "on"; "storage"; storage; "and"; "input"; input] + ["run"; "script"; prg; "on"; "storage"; storage; "and"; "input"; input] -let run_script ?hooks ~src ~storage ~input client = +let run_script ?hooks ~prg ~storage ~input client = let* client_output = - spawn_run_script ?hooks ~src ~storage ~input client + spawn_run_script ?hooks ~prg ~storage ~input client |> Process.check_and_read_stdout in match client_output =~* rex "storage\n(.*)" with diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 0664566483ee..aa8db3aa1ec1 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -660,7 +660,7 @@ val spawn_stresstest : Fails if the new storage cannot be extracted from the output. *) val run_script : ?hooks:Process.hooks -> - src:string -> + prg:string -> storage:string -> input:string -> t -> @@ -669,7 +669,7 @@ val run_script : (** Same as [run_script] but do not wait for the process to exit. *) val spawn_run_script : ?hooks:Process.hooks -> - src:string -> + prg:string -> storage:string -> input:string -> t -> diff --git a/tezt/tests/mockup.ml b/tezt/tests/mockup.ml index 6ee83ce30da4..7201e2a558ab 100644 --- a/tezt/tests/mockup.ml +++ b/tezt/tests/mockup.ml @@ -127,7 +127,7 @@ let test_calling_contract_with_global_constant_success ~protocols = let script = "file:./tezt/tests/contracts/proto_alpha/constant_999.tz" in let storage = "0" in let input = "Unit" in - let* result = Client.run_script ~src:script ~storage ~input client in + let* result = Client.run_script ~prg:script ~storage ~input client in let result = String.trim result in Log.info "Contract with constant output storage %s" result ; if result = value then return () @@ -144,7 +144,7 @@ let test_calling_contract_with_global_constant_failure ~protocols = let script = "file:./tezt/tests/contracts/proto_alpha/constant_999.tz" in let storage = "0" in let input = "Unit" in - let process = Client.spawn_run_script ~src:script ~storage ~input client in + let process = Client.spawn_run_script ~prg:script ~storage ~input client in Process.check_error ~exit_code:1 ~msg:(rex "No registered global was found") -- GitLab From ac591c2193ccb35ca108b3b302f95c30408a26c4 Mon Sep 17 00:00:00 2001 From: Marcin Pastudzki Date: Mon, 20 Dec 2021 15:20:53 +0100 Subject: [PATCH 4/8] Tezt: Add a test for the run script command. For now it tests the behaviour of --self-address and --balance options. --- tezt/lib_tezos/client.ml | 13 +++- tezt/lib_tezos/client.mli | 4 + tezt/tests/main.ml | 2 + tezt/tests/run_script.ml | 158 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 tezt/tests/run_script.ml diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 514a82cc3704..0c41b19ae16a 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -78,6 +78,9 @@ let address ?(hostname = false) ?from peer = | Some endpoint -> Runner.address ~hostname ?from:(runner endpoint) (runner peer) +let optional_arg ~name f = + Option.fold ~none:[] ~some:(fun x -> ["--" ^ name; f x]) + let create_with_mode ?(path = Constant.tezos_client) ?(admin_path = Constant.tezos_admin_client) ?name ?(color = Log.Color.FG.blue) ?base_dir mode = @@ -890,15 +893,17 @@ let stresstest ?endpoint ?source_aliases ?source_pkhs ?source_accounts ?seed client |> Process.check -let spawn_run_script ?hooks ~prg ~storage ~input client = +let spawn_run_script ?hooks ?balance ?self_address ~prg ~storage ~input client = spawn_command ?hooks client - ["run"; "script"; prg; "on"; "storage"; storage; "and"; "input"; input] + (["run"; "script"; prg; "on"; "storage"; storage; "and"; "input"; input] + @ optional_arg ~name:"balance" Tez.to_string balance + @ optional_arg ~name:"self-address" Fun.id self_address) -let run_script ?hooks ~prg ~storage ~input client = +let run_script ?hooks ?balance ?self_address ~prg ~storage ~input client = let* client_output = - spawn_run_script ?hooks ~prg ~storage ~input client + spawn_run_script ?hooks ?balance ?self_address ~prg ~storage ~input client |> Process.check_and_read_stdout in match client_output =~* rex "storage\n(.*)" with diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index aa8db3aa1ec1..09336ea7f52e 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -660,6 +660,8 @@ val spawn_stresstest : Fails if the new storage cannot be extracted from the output. *) val run_script : ?hooks:Process.hooks -> + ?balance:Tez.t -> + ?self_address:string -> prg:string -> storage:string -> input:string -> @@ -669,6 +671,8 @@ val run_script : (** Same as [run_script] but do not wait for the process to exit. *) val spawn_run_script : ?hooks:Process.hooks -> + ?balance:Tez.t -> + ?self_address:string -> prg:string -> storage:string -> input:string -> diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index f29f347d270e..dd24219d1529 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -110,5 +110,7 @@ let () = Sc_rollup.register ~protocols:[Alpha] ; Views.register ~protocols:[Alpha] () ; Runtime_script_failure.register ~protocols ; + (* Relies on a feature only available since J. *) + Run_script.register ~protocols:[Alpha] ; (* Test.run () should be the last statement, don't register afterwards! *) Test.run () diff --git a/tezt/tests/run_script.ml b/tezt/tests/run_script.ml new file mode 100644 index 000000000000..dc2794bab1fe --- /dev/null +++ b/tezt/tests/run_script.ml @@ -0,0 +1,158 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* 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: Client + Invocation: dune exec tezt/tests/main.exe -- --file run_script.ml + Subject: Check that run script command to tezos-client behaves correctly +*) + +(* This script checks it's own address or balance against the expected value + given as parameter. The parameter tells what should be tested and what + the expected value is. If the actual state matches the expected one, + the contract succeeds, otherwise it fails with a pair consisting of the + expected and the actual values. *) +let prg = + {| +parameter (or (mutez %check_balance) (address %check_self_address)) ; +storage unit ; +code { + UNPAIR ; + IF_LEFT { + DUP ; + BALANCE ; + IFCMPEQ { DROP } + { + PUSH string "expected" ; + PAIR ; + BALANCE ; + PUSH string "actual" ; + PAIR ; + PAIR ; + PUSH string "Unexpected BALANCE"; + PAIR ; + FAILWITH ; + } ; + } + { + DUP ; + SELF_ADDRESS ; + IFCMPEQ { DROP } + { + PUSH string "expected" ; + PAIR ; + SELF_ADDRESS; + PUSH string "actual" ; + PAIR ; + PAIR ; + PUSH string "Unexpected SELF_ADDRESS"; + PAIR ; + FAILWITH ; + } ; + }; + NIL operation ; + PAIR ; + } +|} + +let register ~protocol () = + Test.register ~__FILE__ ~title:"Run script" ~tags:["client"; "michelson"] + @@ fun () -> + let* client = Client.init_mockup ~protocol () in + (* With no parameters, the default BALANCE is 4 000 000 ꜩ. *) + let* _storage = + Client.run_script ~prg ~storage:"Unit" ~input:"Left 4000000000000" client + in + + (* When --balance is given, BALANCE should match the expected value. *) + let* _storage = + Client.run_script + ~balance:(Tez.of_int 1) + ~prg + ~storage:"Unit" + ~input:"Left 1000000" + client + in + + let* self_address = + Client.originate_contract + ~burn_cap:(Tez.of_int 1) + ~alias:"test_contract" + ~amount:(Tez.of_int 100) + ~src:"bootstrap1" + ~prg + client + in + + (* When --self-address is given, SELF_ADDRESS should match the given. *) + let* _storage = + Client.run_script + ~self_address + ~prg + ~storage:"Unit" + ~input:(Format.sprintf "Right %S" self_address) + client + in + (* When --self-address is given, BALANCE should be equal to that of the + given account. *) + let* _storage = + Client.run_script + ~self_address + ~prg + ~storage:"Unit" + ~input:"Left 100000000" + client + in + + (* When both --self-address and --balance are given, the BALANCE should be + equal to the given value and SELF_ADDRESS should still match the given. *) + let* _storage = + Client.run_script + ~balance:(Tez.of_int 1) + ~self_address + ~prg + ~storage:"Unit" + ~input:(Format.sprintf "Right %S" self_address) + client + in + let* _storage = + Client.run_script + ~balance:(Tez.of_int 1) + ~self_address + ~prg + ~storage:"Unit" + ~input:"Left 1000000" + client + in + unit + +let register ~protocols = + List.iter + (function + | Protocol.Alpha as protocol -> register ~protocol () + | Protocol.Hangzhou | Protocol.Ithaca -> ()) + (* Won't work prior to protocol J. *) + protocols -- GitLab From b3c60819a3cfc62d84b70a160cbeab211650f1e4 Mon Sep 17 00:00:00 2001 From: Marcin Pastudzki Date: Mon, 10 Jan 2022 08:52:01 +0100 Subject: [PATCH 5/8] Tezt: Add options --source and --payer to the run script command. --- tezt/lib_tezos/client.ml | 19 ++++++++++++++++--- tezt/lib_tezos/client.mli | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 0c41b19ae16a..46aa9c584503 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -893,17 +893,30 @@ let stresstest ?endpoint ?source_aliases ?source_pkhs ?source_accounts ?seed client |> Process.check -let spawn_run_script ?hooks ?balance ?self_address ~prg ~storage ~input client = +let spawn_run_script ?hooks ?balance ?self_address ?source ?payer ~prg ~storage + ~input client = spawn_command ?hooks client (["run"; "script"; prg; "on"; "storage"; storage; "and"; "input"; input] + @ optional_arg ~name:"payer" Fun.id payer + @ optional_arg ~name:"source" Fun.id source @ optional_arg ~name:"balance" Tez.to_string balance @ optional_arg ~name:"self-address" Fun.id self_address) -let run_script ?hooks ?balance ?self_address ~prg ~storage ~input client = +let run_script ?hooks ?balance ?self_address ?source ?payer ~prg ~storage ~input + client = let* client_output = - spawn_run_script ?hooks ?balance ?self_address ~prg ~storage ~input client + spawn_run_script + ?hooks + ?balance + ?source + ?payer + ?self_address + ~prg + ~storage + ~input + client |> Process.check_and_read_stdout in match client_output =~* rex "storage\n(.*)" with diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 09336ea7f52e..1d6ac8ac9a06 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -662,6 +662,8 @@ val run_script : ?hooks:Process.hooks -> ?balance:Tez.t -> ?self_address:string -> + ?source:string -> + ?payer:string -> prg:string -> storage:string -> input:string -> @@ -673,6 +675,8 @@ val spawn_run_script : ?hooks:Process.hooks -> ?balance:Tez.t -> ?self_address:string -> + ?source:string -> + ?payer:string -> prg:string -> storage:string -> input:string -> -- GitLab From 04fe27e1a519be155510456a5ab77dfbbe8a69c1 Mon Sep 17 00:00:00 2001 From: Sventimir Date: Mon, 10 Jan 2022 10:28:57 +0100 Subject: [PATCH 6/8] Tezt: Add tests for --sender and --payer options as well. --- tezt/tests/run_script.ml | 178 +++++++++++++++++++++++++++------------ 1 file changed, 122 insertions(+), 56 deletions(-) diff --git a/tezt/tests/run_script.ml b/tezt/tests/run_script.ml index dc2794bab1fe..1e8ccfd59b66 100644 --- a/tezt/tests/run_script.ml +++ b/tezt/tests/run_script.ml @@ -28,72 +28,66 @@ Component: Client Invocation: dune exec tezt/tests/main.exe -- --file run_script.ml Subject: Check that run script command to tezos-client behaves correctly -*) - -(* This script checks it's own address or balance against the expected value - given as parameter. The parameter tells what should be tested and what - the expected value is. If the actual state matches the expected one, - the contract succeeds, otherwise it fails with a pair consisting of the - expected and the actual values. *) -let prg = + *) + +(* This script checks result of some arbitrary instruction against the + expected value. Return type and name of the instruction should be + given by arguments [ty] and [instr] respectively. The expected + value should be passed to the contract as parameter. If the actual + state matches the expected one, the contract succeeds, otherwise it + fails with a pair consisting of the expected and the actual + values. *) +let prg_template : ('a -> 'b -> 'c -> 'd, unit, string) format = {| -parameter (or (mutez %check_balance) (address %check_self_address)) ; +parameter %s ; /* type */ storage unit ; code { UNPAIR ; - IF_LEFT { - DUP ; - BALANCE ; - IFCMPEQ { DROP } - { - PUSH string "expected" ; - PAIR ; - BALANCE ; - PUSH string "actual" ; - PAIR ; - PAIR ; - PUSH string "Unexpected BALANCE"; - PAIR ; - FAILWITH ; - } ; - } + DUP ; + %s ; /* instr */ + IFCMPEQ { DROP } { - DUP ; - SELF_ADDRESS ; - IFCMPEQ { DROP } - { - PUSH string "expected" ; - PAIR ; - SELF_ADDRESS; - PUSH string "actual" ; - PAIR ; - PAIR ; - PUSH string "Unexpected SELF_ADDRESS"; - PAIR ; - FAILWITH ; - } ; - }; + PUSH string "expected" ; + PAIR ; + %s; /* instr */ + PUSH string "actual" ; + PAIR ; + PAIR ; + FAILWITH ; + } ; NIL operation ; PAIR ; } |} -let register ~protocol () = - Test.register ~__FILE__ ~title:"Run script" ~tags:["client"; "michelson"] - @@ fun () -> +let prg ty instr = Format.sprintf prg_template ty instr instr + +let check_balance = prg "mutez" "BALANCE" + +let check_self_address = prg "address" "SELF_ADDRESS" + +let check_sender = prg "address" "SENDER" + +let check_source = prg "address" "SOURCE" + +let test_balance_and_self_address ~protocol () = let* client = Client.init_mockup ~protocol () in (* With no parameters, the default BALANCE is 4 000 000 ꜩ. *) let* _storage = - Client.run_script ~prg ~storage:"Unit" ~input:"Left 4000000000000" client + Client.run_script + ~prg:check_balance + ~storage:"Unit" + ~input:"4000000000000" + client in (* When --balance is given, BALANCE should match the expected value. *) let* _storage = Client.run_script ~balance:(Tez.of_int 1) - ~prg + ~prg:check_balance ~storage:"Unit" - ~input:"Left 1000000" + ~input:"1000000" client in @@ -103,7 +97,7 @@ let register ~protocol () = ~alias:"test_contract" ~amount:(Tez.of_int 100) ~src:"bootstrap1" - ~prg + ~prg:check_self_address client in @@ -111,9 +105,9 @@ let register ~protocol () = let* _storage = Client.run_script ~self_address - ~prg + ~prg:check_self_address ~storage:"Unit" - ~input:(Format.sprintf "Right %S" self_address) + ~input:(Format.sprintf "%S" self_address) client in (* When --self-address is given, BALANCE should be equal to that of the @@ -121,9 +115,9 @@ let register ~protocol () = let* _storage = Client.run_script ~self_address - ~prg + ~prg:check_balance ~storage:"Unit" - ~input:"Left 100000000" + ~input:"100000000" client in @@ -133,26 +127,98 @@ let register ~protocol () = Client.run_script ~balance:(Tez.of_int 1) ~self_address - ~prg + ~prg:check_self_address ~storage:"Unit" - ~input:(Format.sprintf "Right %S" self_address) + ~input:(Format.sprintf "%S" self_address) client in let* _storage = Client.run_script ~balance:(Tez.of_int 1) ~self_address - ~prg + ~prg:check_balance ~storage:"Unit" - ~input:"Left 1000000" + ~input:"1000000" client in unit +let test_source_and_sender ~protocol () = + let* client = Client.init_mockup ~protocol () in + let* bootstrap1 = Client.show_address ~alias:"bootstrap1" client in + let* bootstrap2 = Client.show_address ~alias:"bootstrap2" client in + + (* When --payer is absent, --source sets *both* SENDER and SOURCE. *) + let* _storage = + Client.run_script + ~source:"bootstrap1" + ~prg:check_source + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap1.public_key_hash) + client + in + let* _storage = + Client.run_script + ~source:"bootstrap1" + ~prg:check_sender + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap1.public_key_hash) + client + in + + (* When --source is absent, --payer sets *both* SENDER and SOURCE. *) + let* _storage = + Client.run_script + ~payer:"bootstrap1" + ~prg:check_source + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap1.public_key_hash) + client + in + let* _storage = + Client.run_script + ~payer:"bootstrap1" + ~prg:check_sender + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap1.public_key_hash) + client + in + + (* When both --source and --payer are given, their values may differ. *) + let* _storage = + Client.run_script + ~payer:"bootstrap1" + ~source:"bootstrap2" + ~prg:check_source + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap1.public_key_hash) + client + in + let* _storage = + Client.run_script + ~payer:"bootstrap1" + ~source:"bootstrap2" + ~prg:check_sender + ~storage:"Unit" + ~input:(Format.sprintf "%S" bootstrap2.public_key_hash) + client + in + unit + +let make_for ~protocol () = + List.iter + (fun (title, f) -> + Test.register ~__FILE__ ~title ~tags:["client"; "michelson"] f) + [ + ( "Run script with balance and self address", + test_balance_and_self_address ~protocol ); + ("Run script with source and sender", test_source_and_sender ~protocol); + ] + let register ~protocols = List.iter (function - | Protocol.Alpha as protocol -> register ~protocol () + | Protocol.Alpha as protocol -> make_for ~protocol () | Protocol.Hangzhou | Protocol.Ithaca -> ()) (* Won't work prior to protocol J. *) protocols -- GitLab From 7d1def85526c598ba633b32b21ce22bb703b83dc Mon Sep 17 00:00:00 2001 From: Sventimir Date: Wed, 12 Jan 2022 15:53:04 +0100 Subject: [PATCH 7/8] Tezt and lib_plugin: create issues for non-standard TODO comments. --- src/proto_alpha/lib_plugin/plugin.ml | 5 +++-- tezt/lib_tezos/client.mli | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index a1d898e12210..1270254f0ffb 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -3224,8 +3224,9 @@ module RPC = struct | (levels, cycles) -> (* explicitly fail when requested levels or cycle are in the past... or too far in the future... - TODO-TB: this old comment (from version Alpha) conflicts with - the specification of the RPCs that use this code. + TODO: https://gitlab.com/tezos/tezos/-/issues/2335 + this old comment (from version Alpha) conflicts with + the specification of the RPCs that use this code. *) List.sort_uniq Level.compare diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 1d6ac8ac9a06..5cb6999675cc 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -372,7 +372,8 @@ val spawn_propose_for : t -> Process.t -(* TODO refactor this *) +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2336 + refactor this *) (** [propose_for] *) val propose_for : @@ -561,8 +562,10 @@ val submit_ballot : val spawn_submit_ballot : ?key:string -> ?wait:string -> proto_hash:string -> ballot -> t -> Process.t -(* TODO: [amount] should be named [transferring] *) -(* TODO: [src] should be named [from] and probably have type [Account.t] *) +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2336 + [amount] should be named [transferring] *) +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2336 + [src] should be named [from] and probably have type [Account.t] *) (** Run [tezos-client originate contract alias transferring amount from src running prg]. Returns the originated contract hash *) -- GitLab From d59309436e2b62ba7136def9e5c21bc4a5f3f0a7 Mon Sep 17 00:00:00 2001 From: Sventimir Date: Fri, 14 Jan 2022 15:06:26 +0100 Subject: [PATCH 8/8] Changes: Mention the new option. --- CHANGES.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index d3ccc2d1ce7f..46e44c78eec8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -39,6 +39,12 @@ Client makes the client inject the transaction in a node even if the simulation of the transaction fails. +- A new ``--self-address`` option was added to the ``run script`` + command. It makes the given address be considered the address of + the contract being run. The address must actually exist in the + context. If ``--balance`` wasn't specified, the script also + inherits the given contract's balance. + Baker / Endorser / Accuser -------------------------- -- GitLab