From bad5666029f26014947b8b45ad6c32e7e040d496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 12 Jan 2022 23:08:32 +0100 Subject: [PATCH 1/7] Client: add a --force option to tezos-client transfer This option makes the client inject the transfer operation even if the simulation fails. --- src/lib_clic/clic.ml | 62 +++++++++++++++++++ src/lib_clic/clic.mli | 41 ++++++++++++ .../lib_client/client_proto_context.ml | 12 ++-- .../lib_client/client_proto_context.mli | 1 + src/proto_alpha/lib_client/injection.ml | 18 ++++-- src/proto_alpha/lib_client/injection.mli | 6 +- .../lib_client/managed_contract.ml | 10 +-- .../lib_client/managed_contract.mli | 1 + .../client_proto_context_commands.ml | 19 +++++- 9 files changed, 153 insertions(+), 17 deletions(-) diff --git a/src/lib_clic/clic.ml b/src/lib_clic/clic.ml index 3513194c7fcb..693b6bdc15b6 100644 --- a/src/lib_clic/clic.ml +++ b/src/lib_clic/clic.ml @@ -1366,6 +1366,68 @@ let args17 spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec17 )); } +let args18 spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 + spec12 spec13 spec14 spec15 spec16 spec17 spec18 = + Argument + { + spec = + spec1 + >> (spec2 + >> (spec3 + >> (spec4 + >> (spec5 + >> (spec6 + >> (spec7 + >> (spec8 + >> (spec9 + >> (spec10 + >> (spec11 + >> (spec12 + >> (spec13 + >> (spec14 + >> (spec15 + >> (spec16 + >> (spec17 + >> (spec18 >> NoArgs)))) + ))))))))))))); + converter = + (fun ( arg1, + ( arg2, + ( arg3, + ( arg4, + ( arg5, + ( spec6, + ( spec7, + ( spec8, + ( spec9, + ( spec10, + ( spec11, + ( spec12, + ( spec13, + ( spec14, + ( spec15, + (spec16, (spec17, (spec18, ()))) ) ) + ) ) ) ) ) ) ) ) ) ) ) ) ) -> + ( arg1, + arg2, + arg3, + arg4, + arg5, + spec6, + spec7, + spec8, + spec9, + spec10, + spec11, + spec12, + spec13, + spec14, + spec15, + spec16, + spec17, + spec18 )); + } + (* Some combinators for writing commands concisely. *) let param ~name ~desc kind next = Param (name, desc, kind, next) diff --git a/src/lib_clic/clic.mli b/src/lib_clic/clic.mli index 677f1795b587..c15840d82b00 100644 --- a/src/lib_clic/clic.mli +++ b/src/lib_clic/clic.mli @@ -359,6 +359,47 @@ val args17 : 'ctx ) options +(** Include 18 optional parameters *) +val args18 : + ('a, 'ctx) arg -> + ('b, 'ctx) arg -> + ('c, 'ctx) arg -> + ('d, 'ctx) arg -> + ('e, 'ctx) arg -> + ('f, 'ctx) arg -> + ('g, 'ctx) arg -> + ('h, 'ctx) arg -> + ('i, 'ctx) arg -> + ('j, 'ctx) arg -> + ('k, 'ctx) arg -> + ('l, 'ctx) arg -> + ('m, 'ctx) arg -> + ('n, 'ctx) arg -> + ('o, 'ctx) arg -> + ('p, 'ctx) arg -> + ('q, 'ctx) arg -> + ('r, 'ctx) arg -> + ( 'a + * 'b + * 'c + * 'd + * 'e + * 'f + * 'g + * 'h + * 'i + * 'j + * 'k + * 'l + * 'm + * 'n + * 'o + * 'p + * 'q + * 'r, + 'ctx ) + options + (** {2 Parameter based command lines} *) (** Type of parameters for a command *) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index ae75c1f8e330..5b65d975b954 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -105,9 +105,9 @@ let build_transaction_operation ~amount ~parameters operation let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~destination - ?(entrypoint = Entrypoint.default) ?arg ~amount ?fee ?gas_limit - ?storage_limit ?counter ~fee_parameter ?replace_by_fees () = + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~destination ?(entrypoint = Entrypoint.default) ?arg ~amount ?fee + ?gas_limit ?storage_limit ?counter ~fee_parameter ?replace_by_fees () = parse_arg_transfer arg >>=? fun parameters -> let contents = build_transaction_operation @@ -128,6 +128,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -140,7 +141,8 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter contents >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force 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) @@ -376,7 +378,7 @@ let originate_contract (cctxt : #full) ~chain ~block ?confirmations ?dry_run | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return (oph, op, result)) >>=? fun res -> - Lwt.return (Injection.originated_contracts result) >>=? function + Lwt.return (Injection.originated_contracts ~force:false result) >>=? function | [contract] -> return (res, contract) | contracts -> failwith diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index 6fdbc4e62128..f3fef8405783 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -208,6 +208,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 1aa906a326db..942ef9d0e6b7 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -432,6 +432,11 @@ let rec originated_contracts : type kind. kind contents_result_list -> _ = originated_contracts rest >>? fun contracts2 -> Ok (List.rev_append contracts1 contracts2) +(* When --force is used, we don't want [originated_contracts] to fail as + it would stop the client before the injection of the operation. *) +let originated_contracts ~force results = + match originated_contracts results with Error _ when force -> Ok [] | e -> e + let detect_script_failure : type kind. kind operation_metadata -> _ = let rec detect_script_failure : type kind. kind contents_result_list -> _ = let detect_script_failure_single (type kind) @@ -833,8 +838,8 @@ let tenderbake_adjust_confirmations (cctxt : #Client_context.full) = function were tenderbake_finality_confirmations. *) let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations - ?(dry_run = false) ?(simulation = false) ?branch ?src_sk ?verbose_signing - ~fee_parameter (contents : kind contents_list) = + ?(dry_run = false) ?(simulation = false) ?(force = false) ?branch ?src_sk + ?verbose_signing ~fee_parameter (contents : kind contents_list) = (if simulation then simulate cctxt ~chain ~block ?branch contents else preapply @@ -854,7 +859,7 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations "@[This simulation failed:@,%a@]" Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) - >>= fun () -> Lwt.return res) + >>= fun () -> if force then return_unit else Lwt.return res) >>=? fun () -> let bytes = Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) @@ -926,7 +931,8 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) >>= fun () -> - Lwt.return (originated_contracts result.contents) >>=? fun contracts -> + Lwt.return (originated_contracts result.contents ~force) + >>=? fun contracts -> List.iter_s (fun c -> cctxt#message "New contract %a originated." Contract.pp c) contracts @@ -1165,7 +1171,7 @@ let may_replace_operation (type kind) (cctxt : #full) chain from Lwt.return_ok contents let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run - ?verbose_signing ?simulation ~source ~src_pk ~src_sk ~fee ~gas_limit + ?verbose_signing ?simulation ?force ~source ~src_pk ~src_sk ~fee ~gas_limit ~storage_limit ?counter ?(replace_by_fees = false) ~fee_parameter (type kind) (operations : kind Annotated_manager_operation.annotated_list) : (Operation_hash.t @@ -1244,6 +1250,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?confirmations ?dry_run ?simulation + ?force ~fee_parameter ?verbose_signing ?branch @@ -1275,6 +1282,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ?force ~fee_parameter ?branch ~src_sk diff --git a/src/proto_alpha/lib_client/injection.mli b/src/proto_alpha/lib_client/injection.mli index 1fba94f4a0e2..21b1301e09e4 100644 --- a/src/proto_alpha/lib_client/injection.mli +++ b/src/proto_alpha/lib_client/injection.mli @@ -90,6 +90,7 @@ val inject_manager_operation : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> source:Signature.Public_key_hash.t -> src_pk:Signature.public_key -> src_sk:Client_keys.sk_uri -> @@ -102,5 +103,8 @@ val inject_manager_operation : 'kind Annotated_manager_operation.annotated_list -> 'kind Kind.manager result_list tzresult Lwt.t +(** Collects the addresses of all contracts originated by a batch of operations + by looking at the operation results. Fails if an operation in the batch is + failed unless [force] is given. *) val originated_contracts : - 'kind contents_result_list -> Contract.t list tzresult + force:bool -> 'kind contents_result_list -> Contract.t list tzresult diff --git a/src/proto_alpha/lib_client/managed_contract.ml b/src/proto_alpha/lib_client/managed_contract.ml index 676a7d95b03b..3fb104560851 100644 --- a/src/proto_alpha/lib_client/managed_contract.ml +++ b/src/proto_alpha/lib_client/managed_contract.ml @@ -285,9 +285,9 @@ let build_transaction_operation (cctxt : #full) ~chain ~block ~contract contract) let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~contract - ~destination ?(entrypoint = Entrypoint.default) ?arg ~amount ?fee ?gas_limit - ?storage_limit ?counter ~fee_parameter () : + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~contract ~destination ?(entrypoint = Entrypoint.default) ?arg + ~amount ?fee ?gas_limit ?storage_limit ?counter ~fee_parameter () : (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult Lwt.t = build_transaction_operation @@ -313,6 +313,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -324,6 +325,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter operation >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force result) + >>=? fun contracts -> return_single_manager_result (oph, op, result) >>=? fun res -> return (res, contracts) diff --git a/src/proto_alpha/lib_client/managed_contract.mli b/src/proto_alpha/lib_client/managed_contract.mli index e272420913a9..cc40c9caa8ff 100644 --- a/src/proto_alpha/lib_client/managed_contract.mli +++ b/src/proto_alpha/lib_client/managed_contract.mli @@ -93,6 +93,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> 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 591df1d6eac9..9712bf3da64c 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 @@ -640,11 +640,18 @@ let simulate_switch = "Simulate the execution of the command, without needing any signatures." () +let force_switch = + Clic.switch + ~long:"force" + ~doc:"Inject the operation even if the simulation results in a failure." + () + let transfer_command amount source destination cctxt ( fee, dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -681,6 +688,7 @@ let transfer_command amount source destination cctxt ~dry_run ~verbose_signing ~simulation + ~force ~fee_parameter ?fee ~contract @@ -704,6 +712,7 @@ let transfer_command amount source destination cctxt ?confirmations:cctxt#confirmations ~dry_run ~simulation + ~force ~verbose_signing ~fee_parameter ~source @@ -1277,11 +1286,12 @@ let commands_rw () = command ~group ~desc:"Transfer tokens / call a smart contract." - (args17 + (args18 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -1310,6 +1320,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1336,6 +1347,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1433,11 +1445,12 @@ let commands_rw () = command ~group ~desc:"Call a smart contract (same as 'transfer 0')." - (args17 + (args18 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -1464,6 +1477,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1490,6 +1504,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, -- GitLab From f165734e1151ca42921d5362d5b62ebc61e571cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Thu, 13 Jan 2022 16:03:43 +0100 Subject: [PATCH 2/7] Client/Hangzhou+Ithaca: backport the --force option --- .../lib_client/client_proto_context.ml | 12 +++++++----- .../lib_client/client_proto_context.mli | 1 + .../lib_client/injection.ml | 18 +++++++++++++----- .../lib_client/injection.mli | 6 +++++- .../lib_client/managed_contract.ml | 10 ++++++---- .../lib_client/managed_contract.mli | 1 + .../client_proto_context_commands.ml | 19 +++++++++++++++++-- .../lib_client/client_proto_context.ml | 12 +++++++----- .../lib_client/client_proto_context.mli | 1 + .../lib_client/injection.ml | 18 +++++++++++++----- .../lib_client/injection.mli | 6 +++++- .../lib_client/managed_contract.ml | 10 ++++++---- .../lib_client/managed_contract.mli | 1 + .../client_proto_context_commands.ml | 19 +++++++++++++++++-- 14 files changed, 100 insertions(+), 34 deletions(-) diff --git a/src/proto_011_PtHangz2/lib_client/client_proto_context.ml b/src/proto_011_PtHangz2/lib_client/client_proto_context.ml index 459fcc41da91..e53f8948ecb9 100644 --- a/src/proto_011_PtHangz2/lib_client/client_proto_context.ml +++ b/src/proto_011_PtHangz2/lib_client/client_proto_context.ml @@ -101,9 +101,9 @@ let build_transaction_operation ~amount ~parameters ?(entrypoint = "default") operation let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~destination - ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit ?storage_limit - ?counter ~fee_parameter () = + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~destination ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit + ?storage_limit ?counter ~fee_parameter () = parse_arg_transfer arg >>=? fun parameters -> let contents = build_transaction_operation @@ -124,6 +124,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -135,7 +136,8 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter contents >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force 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) @@ -338,7 +340,7 @@ let originate_contract (cctxt : #full) ~chain ~block ?confirmations ?dry_run | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return (oph, op, result)) >>=? fun res -> - Lwt.return (Injection.originated_contracts result) >>=? function + Lwt.return (Injection.originated_contracts ~force:false result) >>=? function | [contract] -> return (res, contract) | contracts -> failwith diff --git a/src/proto_011_PtHangz2/lib_client/client_proto_context.mli b/src/proto_011_PtHangz2/lib_client/client_proto_context.mli index c5dc30b57e24..ba5306132ed8 100644 --- a/src/proto_011_PtHangz2/lib_client/client_proto_context.mli +++ b/src/proto_011_PtHangz2/lib_client/client_proto_context.mli @@ -185,6 +185,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> diff --git a/src/proto_011_PtHangz2/lib_client/injection.ml b/src/proto_011_PtHangz2/lib_client/injection.ml index 9d68cdd14425..d9712d786715 100644 --- a/src/proto_011_PtHangz2/lib_client/injection.ml +++ b/src/proto_011_PtHangz2/lib_client/injection.ml @@ -407,6 +407,11 @@ let rec originated_contracts : type kind. kind contents_result_list -> _ = originated_contracts rest >>? fun contracts2 -> Ok (List.rev_append contracts1 contracts2) +(* When --force is used, we don't want [originated_contracts] to fail as + it would stop the client before the injection of the operation. *) +let originated_contracts ~force results = + match originated_contracts results with Error _ when force -> Ok [] | e -> e + let detect_script_failure : type kind. kind operation_metadata -> _ = let rec detect_script_failure : type kind. kind contents_result_list -> _ = let detect_script_failure_single (type kind) @@ -780,8 +785,8 @@ let may_patch_limits (type kind) (cctxt : #Protocol_client_context.full) annotated_contents) let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations - ?(dry_run = false) ?(simulation = false) ?branch ?src_sk ?verbose_signing - ~fee_parameter (contents : kind contents_list) = + ?(dry_run = false) ?(simulation = false) ?(force = false) ?branch ?src_sk + ?verbose_signing ~fee_parameter (contents : kind contents_list) = (if simulation then simulate cctxt ~chain ~block ?branch contents else preapply @@ -801,7 +806,7 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations "@[This simulation failed:@,%a@]" Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) - >>= fun () -> Lwt.return res) + >>= fun () -> if force then return_unit else Lwt.return res) >>=? fun () -> let bytes = Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) @@ -871,7 +876,8 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) >>= fun () -> - Lwt.return (originated_contracts result.contents) >>=? fun contracts -> + Lwt.return (originated_contracts result.contents ~force) + >>=? fun contracts -> List.iter_s (fun c -> cctxt#message "New contract %a originated." Contract.pp c) contracts @@ -937,7 +943,7 @@ let reveal_error (cctxt : #Protocol_client_context.full) = cctxt#error "%s" reveal_error_message let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run - ?verbose_signing ?simulation ~source ~src_pk ~src_sk ~fee ~gas_limit + ?verbose_signing ?simulation ?force ~source ~src_pk ~src_sk ~fee ~gas_limit ~storage_limit ?counter ~fee_parameter (type kind) (operations : kind Annotated_manager_operation.annotated_list) : (Operation_hash.t @@ -1010,6 +1016,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?confirmations ?dry_run ?simulation + ?force ~fee_parameter ?verbose_signing ?branch @@ -1035,6 +1042,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ?force ~fee_parameter ?branch ~src_sk diff --git a/src/proto_011_PtHangz2/lib_client/injection.mli b/src/proto_011_PtHangz2/lib_client/injection.mli index d8f99d620510..50da92f06c55 100644 --- a/src/proto_011_PtHangz2/lib_client/injection.mli +++ b/src/proto_011_PtHangz2/lib_client/injection.mli @@ -90,6 +90,7 @@ val inject_manager_operation : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> source:Signature.Public_key_hash.t -> src_pk:Signature.public_key -> src_sk:Client_keys.sk_uri -> @@ -101,5 +102,8 @@ val inject_manager_operation : 'kind Annotated_manager_operation.annotated_list -> 'kind Kind.manager result_list tzresult Lwt.t +(** Collects the addresses of all contracts originated by a batch of operations + by looking at the operation results. Fails if an operation in the batch is + failed unless [force] is given. *) val originated_contracts : - 'kind contents_result_list -> Contract.t list tzresult + force:bool -> 'kind contents_result_list -> Contract.t list tzresult diff --git a/src/proto_011_PtHangz2/lib_client/managed_contract.ml b/src/proto_011_PtHangz2/lib_client/managed_contract.ml index 29bb3d976b63..cbc1db16a4eb 100644 --- a/src/proto_011_PtHangz2/lib_client/managed_contract.ml +++ b/src/proto_011_PtHangz2/lib_client/managed_contract.ml @@ -277,9 +277,9 @@ let build_transaction_operation (cctxt : #full) ~chain ~block ~contract contract) let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~contract - ~destination ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit - ?storage_limit ?counter ~fee_parameter () : + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~contract ~destination ?(entrypoint = "default") ?arg ~amount ?fee + ?gas_limit ?storage_limit ?counter ~fee_parameter () : (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult Lwt.t = build_transaction_operation @@ -305,6 +305,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -316,6 +317,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter operation >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force result) + >>=? fun contracts -> return_single_manager_result (oph, op, result) >>=? fun res -> return (res, contracts) diff --git a/src/proto_011_PtHangz2/lib_client/managed_contract.mli b/src/proto_011_PtHangz2/lib_client/managed_contract.mli index ae532c986987..bb467b5482e8 100644 --- a/src/proto_011_PtHangz2/lib_client/managed_contract.mli +++ b/src/proto_011_PtHangz2/lib_client/managed_contract.mli @@ -93,6 +93,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> diff --git a/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml b/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml index bad29a4fde77..184ee03b5080 100644 --- a/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml @@ -56,6 +56,12 @@ let simulate_switch = "Simulate the execution of the command, without needing any signatures." () +let force_switch = + Clic.switch + ~long:"force" + ~doc:"Inject the operation even if the simulation results in a failure." + () + let report_michelson_errors ?(no_print_source = false) ~msg (cctxt : #Client_context.printer) = function | Error errs -> @@ -109,6 +115,7 @@ let transfer_command amount source destination cctxt dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -144,6 +151,7 @@ let transfer_command amount source destination cctxt ~dry_run ~verbose_signing ~simulation + ~force ~fee_parameter ?fee ~contract @@ -167,6 +175,7 @@ let transfer_command amount source destination cctxt ?confirmations:cctxt#confirmations ~dry_run ~simulation + ~force ~verbose_signing ~fee_parameter ~source @@ -948,11 +957,12 @@ let commands network () = command ~group ~desc:"Transfer tokens / call a smart contract." - (args16 + (args17 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -980,6 +990,7 @@ let commands network () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1005,6 +1016,7 @@ let commands network () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1101,11 +1113,12 @@ let commands network () = command ~group ~desc:"Call a smart contract (same as 'transfer 0')." - (args16 + (args17 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -1131,6 +1144,7 @@ let commands network () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1156,6 +1170,7 @@ let commands network () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, diff --git a/src/proto_012_PsiThaCa/lib_client/client_proto_context.ml b/src/proto_012_PsiThaCa/lib_client/client_proto_context.ml index d55e8eb9f321..718ca408e4ca 100644 --- a/src/proto_012_PsiThaCa/lib_client/client_proto_context.ml +++ b/src/proto_012_PsiThaCa/lib_client/client_proto_context.ml @@ -104,9 +104,9 @@ let build_transaction_operation ~amount ~parameters ?(entrypoint = "default") operation let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~destination - ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit ?storage_limit - ?counter ~fee_parameter () = + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~destination ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit + ?storage_limit ?counter ~fee_parameter () = parse_arg_transfer arg >>=? fun parameters -> let contents = build_transaction_operation @@ -127,6 +127,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -138,7 +139,8 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter contents >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force 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) @@ -374,7 +376,7 @@ let originate_contract (cctxt : #full) ~chain ~block ?confirmations ?dry_run | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return (oph, op, result)) >>=? fun res -> - Lwt.return (Injection.originated_contracts result) >>=? function + Lwt.return (Injection.originated_contracts ~force:false result) >>=? function | [contract] -> return (res, contract) | contracts -> failwith diff --git a/src/proto_012_PsiThaCa/lib_client/client_proto_context.mli b/src/proto_012_PsiThaCa/lib_client/client_proto_context.mli index 05d01ac753ef..5cf83c93f133 100644 --- a/src/proto_012_PsiThaCa/lib_client/client_proto_context.mli +++ b/src/proto_012_PsiThaCa/lib_client/client_proto_context.mli @@ -208,6 +208,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> diff --git a/src/proto_012_PsiThaCa/lib_client/injection.ml b/src/proto_012_PsiThaCa/lib_client/injection.ml index a60dddcb4fd9..862e9f78396a 100644 --- a/src/proto_012_PsiThaCa/lib_client/injection.ml +++ b/src/proto_012_PsiThaCa/lib_client/injection.ml @@ -414,6 +414,11 @@ let rec originated_contracts : type kind. kind contents_result_list -> _ = originated_contracts rest >>? fun contracts2 -> Ok (List.rev_append contracts1 contracts2) +(* When --force is used, we don't want [originated_contracts] to fail as + it would stop the client before the injection of the operation. *) +let originated_contracts ~force results = + match originated_contracts results with Error _ when force -> Ok [] | e -> e + let detect_script_failure : type kind. kind operation_metadata -> _ = let rec detect_script_failure : type kind. kind contents_result_list -> _ = let detect_script_failure_single (type kind) @@ -808,8 +813,8 @@ let tenderbake_adjust_confirmations (cctxt : #Client_context.full) = function were tenderbake_finality_confirmations. *) let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations - ?(dry_run = false) ?(simulation = false) ?branch ?src_sk ?verbose_signing - ~fee_parameter (contents : kind contents_list) = + ?(dry_run = false) ?(simulation = false) ?(force = false) ?branch ?src_sk + ?verbose_signing ~fee_parameter (contents : kind contents_list) = (if simulation then simulate cctxt ~chain ~block ?branch contents else preapply @@ -829,7 +834,7 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations "@[This simulation failed:@,%a@]" Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) - >>= fun () -> Lwt.return res) + >>= fun () -> if force then return_unit else Lwt.return res) >>=? fun () -> let bytes = Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) @@ -901,7 +906,8 @@ let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations Operation_result.pp_operation_result (op.protocol_data.contents, result.contents) >>= fun () -> - Lwt.return (originated_contracts result.contents) >>=? fun contracts -> + Lwt.return (originated_contracts result.contents ~force) + >>=? fun contracts -> List.iter_s (fun c -> cctxt#message "New contract %a originated." Contract.pp c) contracts @@ -967,7 +973,7 @@ let reveal_error (cctxt : #Protocol_client_context.full) = cctxt#error "%s" reveal_error_message let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run - ?verbose_signing ?simulation ~source ~src_pk ~src_sk ~fee ~gas_limit + ?verbose_signing ?simulation ?force ~source ~src_pk ~src_sk ~fee ~gas_limit ~storage_limit ?counter ~fee_parameter (type kind) (operations : kind Annotated_manager_operation.annotated_list) : (Operation_hash.t @@ -1040,6 +1046,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?confirmations ?dry_run ?simulation + ?force ~fee_parameter ?verbose_signing ?branch @@ -1065,6 +1072,7 @@ let inject_manager_operation cctxt ~chain ~block ?branch ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ?force ~fee_parameter ?branch ~src_sk diff --git a/src/proto_012_PsiThaCa/lib_client/injection.mli b/src/proto_012_PsiThaCa/lib_client/injection.mli index d8f99d620510..50da92f06c55 100644 --- a/src/proto_012_PsiThaCa/lib_client/injection.mli +++ b/src/proto_012_PsiThaCa/lib_client/injection.mli @@ -90,6 +90,7 @@ val inject_manager_operation : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> source:Signature.Public_key_hash.t -> src_pk:Signature.public_key -> src_sk:Client_keys.sk_uri -> @@ -101,5 +102,8 @@ val inject_manager_operation : 'kind Annotated_manager_operation.annotated_list -> 'kind Kind.manager result_list tzresult Lwt.t +(** Collects the addresses of all contracts originated by a batch of operations + by looking at the operation results. Fails if an operation in the batch is + failed unless [force] is given. *) val originated_contracts : - 'kind contents_result_list -> Contract.t list tzresult + force:bool -> 'kind contents_result_list -> Contract.t list tzresult diff --git a/src/proto_012_PsiThaCa/lib_client/managed_contract.ml b/src/proto_012_PsiThaCa/lib_client/managed_contract.ml index 29bb3d976b63..cbc1db16a4eb 100644 --- a/src/proto_012_PsiThaCa/lib_client/managed_contract.ml +++ b/src/proto_012_PsiThaCa/lib_client/managed_contract.ml @@ -277,9 +277,9 @@ let build_transaction_operation (cctxt : #full) ~chain ~block ~contract contract) let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?simulation ?branch ~source ~src_pk ~src_sk ~contract - ~destination ?(entrypoint = "default") ?arg ~amount ?fee ?gas_limit - ?storage_limit ?counter ~fee_parameter () : + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~contract ~destination ?(entrypoint = "default") ?arg ~amount ?fee + ?gas_limit ?storage_limit ?counter ~fee_parameter () : (Kind.transaction Kind.manager Injection.result * Contract.t list) tzresult Lwt.t = build_transaction_operation @@ -305,6 +305,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?dry_run ?verbose_signing ?simulation + ~force ?branch ~source ~fee:(Limit.of_option fee) @@ -316,6 +317,7 @@ let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run ~fee_parameter operation >>=? fun (oph, op, result) -> - Lwt.return (Injection.originated_contracts result) >>=? fun contracts -> + Lwt.return (Injection.originated_contracts ~force result) + >>=? fun contracts -> return_single_manager_result (oph, op, result) >>=? fun res -> return (res, contracts) diff --git a/src/proto_012_PsiThaCa/lib_client/managed_contract.mli b/src/proto_012_PsiThaCa/lib_client/managed_contract.mli index ae532c986987..bb467b5482e8 100644 --- a/src/proto_012_PsiThaCa/lib_client/managed_contract.mli +++ b/src/proto_012_PsiThaCa/lib_client/managed_contract.mli @@ -93,6 +93,7 @@ val transfer : ?dry_run:bool -> ?verbose_signing:bool -> ?simulation:bool -> + ?force:bool -> ?branch:int -> source:public_key_hash -> src_pk:public_key -> diff --git a/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml b/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml index 077fadc50d62..df43f2952c58 100644 --- a/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml @@ -584,11 +584,18 @@ let simulate_switch = "Simulate the execution of the command, without needing any signatures." () +let force_switch = + Clic.switch + ~long:"force" + ~doc:"Inject the operation even if the simulation results in a failure." + () + let transfer_command amount source destination cctxt ( fee, dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -624,6 +631,7 @@ let transfer_command amount source destination cctxt ~dry_run ~verbose_signing ~simulation + ~force ~fee_parameter ?fee ~contract @@ -647,6 +655,7 @@ let transfer_command amount source destination cctxt ?confirmations:cctxt#confirmations ~dry_run ~simulation + ~force ~verbose_signing ~fee_parameter ~source @@ -1216,11 +1225,12 @@ let commands_rw () = command ~group ~desc:"Transfer tokens / call a smart contract." - (args16 + (args17 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -1248,6 +1258,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1273,6 +1284,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1369,11 +1381,12 @@ let commands_rw () = command ~group ~desc:"Call a smart contract (same as 'transfer 0')." - (args16 + (args17 fee_arg dry_run_switch verbose_signing_switch simulate_switch + force_switch gas_limit_arg storage_limit_arg counter_arg @@ -1399,6 +1412,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, @@ -1424,6 +1438,7 @@ let commands_rw () = dry_run, verbose_signing, simulation, + force, gas_limit, storage_limit, counter, -- GitLab From 01dea0d24669b90969161111545673f8071479fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Wed, 12 Jan 2022 23:09:46 +0100 Subject: [PATCH 3/7] Tezt: add support for the --force option of tezos-client transfer --- tezt/lib_tezos/client.ml | 9 ++++++--- tezt/lib_tezos/client.mli | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index ad7ca13760ce..46f02e10e110 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -566,7 +566,8 @@ let gen_and_show_keys ?alias client = show_address ~alias client let spawn_transfer ?hooks ?endpoint ?(wait = "none") ?burn_cap ?fee ?gas_limit - ?storage_limit ?counter ?arg ~amount ~giver ~receiver client = + ?storage_limit ?counter ?arg ?(force = false) ~amount ~giver ~receiver + client = spawn_command ?endpoint ?hooks @@ -593,10 +594,11 @@ let spawn_transfer ?hooks ?endpoint ?(wait = "none") ?burn_cap ?fee ?gas_limit ~none:[] ~some:(fun s -> ["--counter"; string_of_int s]) counter - @ Option.fold ~none:[] ~some:(fun p -> ["--arg"; p]) arg) + @ Option.fold ~none:[] ~some:(fun p -> ["--arg"; p]) arg + @ if force then ["--force"] else []) let transfer ?hooks ?endpoint ?wait ?burn_cap ?fee ?gas_limit ?storage_limit - ?counter ?arg ~amount ~giver ~receiver client = + ?counter ?arg ?force ~amount ~giver ~receiver client = spawn_transfer ?endpoint ?hooks @@ -607,6 +609,7 @@ let transfer ?hooks ?endpoint ?wait ?burn_cap ?fee ?gas_limit ?storage_limit ?storage_limit ?counter ?arg + ?force ~amount ~giver ~receiver diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index a2ac462dc584..0664566483ee 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -422,6 +422,7 @@ val transfer : ?storage_limit:int -> ?counter:int -> ?arg:string -> + ?force:bool -> amount:Tez.t -> giver:string -> receiver:string -> @@ -439,6 +440,7 @@ val spawn_transfer : ?storage_limit:int -> ?counter:int -> ?arg:string -> + ?force:bool -> amount:Tez.t -> giver:string -> receiver:string -> -- GitLab From 6a2380e768512b1efe7dd18dc4ac16ece40aba4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Thu, 13 Jan 2022 15:30:56 +0100 Subject: [PATCH 4/7] Tests/Integration: tezt test for `tezos-client transfer --force` --- .../contracts/proto_alpha/always_fails.tz | 3 + tezt/tests/main.ml | 1 + tezt/tests/runtime_script_failure.ml | 83 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 tezt/tests/contracts/proto_alpha/always_fails.tz create mode 100644 tezt/tests/runtime_script_failure.ml diff --git a/tezt/tests/contracts/proto_alpha/always_fails.tz b/tezt/tests/contracts/proto_alpha/always_fails.tz new file mode 100644 index 000000000000..54014f82672d --- /dev/null +++ b/tezt/tests/contracts/proto_alpha/always_fails.tz @@ -0,0 +1,3 @@ +parameter string; +storage unit; +code FAILWITH diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index 792fd66ccb45..f29f347d270e 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -109,5 +109,6 @@ let () = Replace_by_fees.register ~protocols:[Alpha] ; Sc_rollup.register ~protocols:[Alpha] ; Views.register ~protocols:[Alpha] () ; + Runtime_script_failure.register ~protocols ; (* Test.run () should be the last statement, don't register afterwards! *) Test.run () diff --git a/tezt/tests/runtime_script_failure.ml b/tezt/tests/runtime_script_failure.ml new file mode 100644 index 000000000000..815df7e297b5 --- /dev/null +++ b/tezt/tests/runtime_script_failure.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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 + ------- + Components: Client + Invocation: dune exec tezt/tests/main.exe -- runtime_script_failure + Subject: Test that the --force option of the transfer command can be used + to include an invalid operation in a block +*) + +let check_client_force = + Protocol.register_test + ~__FILE__ + ~title:"Runtime Script Failure: client force" + ~tags:["runtime_script_failure"] + @@ fun protocol -> + let* node = Node.init [Synchronisation_threshold 0; Connections 0] in + let* client = Client.init ~endpoint:(Node node) () in + let* () = Client.activate_protocol ~protocol client in + let* _ = Node.wait_for_level node 1 in + let* contract_id = + Client.originate_contract + ~alias:"always_fails" + ~amount:Tez.zero + ~src:"bootstrap1" + ~prg:"file:./tezt/tests/contracts/proto_alpha/always_fails.tz" + ~init:"Unit" + ~burn_cap:Tez.(of_int 1) + client + in + let* () = Client.bake_for client in + let* () = + Client.transfer + ~gas_limit:100_000 + ~fee:Tez.one + ~amount:Tez.zero + ~burn_cap:Tez.zero + ~storage_limit:10000 + ~giver:"bootstrap1" + ~receiver:contract_id + ~arg:"20" + ~force:true + client + in + let* () = Client.bake_for client in + let* first_manager_operation = + Client.rpc + Client.GET + ["chains"; "main"; "blocks"; "head"; "operations"; "3"; "0"] + client + in + let first_result = + JSON.( + first_manager_operation |-> "contents" |=> 0 |-> "metadata" + |-> "operation_result" |-> "status" |> as_string) + in + assert (first_result = "failed") ; + return () + +let register ~protocols = check_client_force ~protocols -- GitLab From 0b0c044ae4a58bedd461ae9691ce0e5299fdc066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Thu, 13 Jan 2022 18:31:22 +0100 Subject: [PATCH 5/7] Changes: add a mention on `tezos-client transfer --force` --- CHANGES.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index b874566e6f41..406692137e56 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -30,6 +30,10 @@ Node Client ------ +- A new ``--force`` option was added to the ``transfer`` command. It + makes the client inject the transaction in a node even if the + simulation of the transaction fails. + Baker / Endorser / Accuser -------------------------- -- GitLab From 1f91409f30d4fd70e3e062b02ab2b63d88b9454a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Fri, 14 Jan 2022 16:27:01 +0100 Subject: [PATCH 6/7] Client/Alpha: `tezos-client transfer --force` requires 3 options `tezos-client transfer --force` requires `--gas-limit`, `--storage-limit`, and `--fee`. --- .../client_proto_context_commands.ml | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) 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 9712bf3da64c..72b4f1df5971 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 @@ -643,10 +643,12 @@ let simulate_switch = let force_switch = Clic.switch ~long:"force" - ~doc:"Inject the operation even if the simulation results in a failure." + ~doc: + "Inject the operation even if the simulation results in a failure. This \ + switch requires --gas-limit, --storage-limit, and --fee." () -let transfer_command amount source destination cctxt +let transfer_command amount source destination (cctxt : #Client_context.printer) ( fee, dry_run, verbose_signing, @@ -675,6 +677,22 @@ let transfer_command amount source destination cctxt burn_cap; } in + (* When --force is used we want to inject the transfer even if it fails. + In that case we cannot rely on simulation to compute limits and fees + so we require the corresponding options to be set. *) + let check_force_dependency name = function + | None -> + cctxt#error + "When the --force switch is used, the %s option is required." + name + | _ -> Lwt.return_unit + in + (if force then + check_force_dependency "--gas-limit" gas_limit >>= fun () -> + check_force_dependency "--storage-limit" storage_limit >>= fun () -> + check_force_dependency "--fee" fee + else Lwt.return_unit) + >>= fun () -> (match Contract.is_implicit source with | None -> let contract = source in -- GitLab From 89cc5412b80eb69da44e727eb2e0d0b746f5749f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Cauderlier?= Date: Fri, 14 Jan 2022 16:34:12 +0100 Subject: [PATCH 7/7] Client/Hangzhou+Ithaca: backport change of previous commit --- .../client_proto_context_commands.ml | 22 +++++++++++++++++-- .../client_proto_context_commands.ml | 22 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml b/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml index 184ee03b5080..9885bc0090bd 100644 --- a/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_011_PtHangz2/lib_client_commands/client_proto_context_commands.ml @@ -59,7 +59,9 @@ let simulate_switch = let force_switch = Clic.switch ~long:"force" - ~doc:"Inject the operation even if the simulation results in a failure." + ~doc: + "Inject the operation even if the simulation results in a failure. This \ + switch requires --gas-limit, --storage-limit, and --fee." () let report_michelson_errors ?(no_print_source = false) ~msg @@ -110,7 +112,7 @@ let alphanet = {Clic.name = "alphanet"; title = "Alphanet only commands"} let binary_description = {Clic.name = "description"; title = "Binary Description"} -let transfer_command amount source destination cctxt +let transfer_command amount source destination (cctxt : #Client_context.printer) ( fee, dry_run, verbose_signing, @@ -138,6 +140,22 @@ let transfer_command amount source destination cctxt burn_cap; } in + (* When --force is used we want to inject the transfer even if it fails. + In that case we cannot rely on simulation to compute limits and fees + so we require the corresponding options to be set. *) + let check_force_dependency name = function + | None -> + cctxt#error + "When the --force switch is used, the %s option is required." + name + | _ -> Lwt.return_unit + in + (if force then + check_force_dependency "--gas-limit" gas_limit >>= fun () -> + check_force_dependency "--storage-limit" storage_limit >>= fun () -> + check_force_dependency "--fee" fee + else Lwt.return_unit) + >>= fun () -> (match Contract.is_implicit source with | None -> let contract = source in diff --git a/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml b/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml index df43f2952c58..65729e330f1c 100644 --- a/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_012_PsiThaCa/lib_client_commands/client_proto_context_commands.ml @@ -587,10 +587,12 @@ let simulate_switch = let force_switch = Clic.switch ~long:"force" - ~doc:"Inject the operation even if the simulation results in a failure." + ~doc: + "Inject the operation even if the simulation results in a failure. This \ + switch requires --gas-limit, --storage-limit, and --fee." () -let transfer_command amount source destination cctxt +let transfer_command amount source destination (cctxt : #Client_context.printer) ( fee, dry_run, verbose_signing, @@ -618,6 +620,22 @@ let transfer_command amount source destination cctxt burn_cap; } in + (* When --force is used we want to inject the transfer even if it fails. + In that case we cannot rely on simulation to compute limits and fees + so we require the corresponding options to be set. *) + let check_force_dependency name = function + | None -> + cctxt#error + "When the --force switch is used, the %s option is required." + name + | _ -> Lwt.return_unit + in + (if force then + check_force_dependency "--gas-limit" gas_limit >>= fun () -> + check_force_dependency "--storage-limit" storage_limit >>= fun () -> + check_force_dependency "--fee" fee + else Lwt.return_unit) + >>= fun () -> (match Contract.is_implicit source with | None -> let contract = source in -- GitLab