From b27d94d223893c0d6980d87d5db88362c546ae5a Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Tue, 25 Jul 2023 15:46:56 +0200 Subject: [PATCH 1/4] Validation/proto_plugin: pack syntactic check into proto functions --- src/lib_validation/protocol_plugin.ml | 70 ++++++++++++++++++-------- src/lib_validation/protocol_plugin.mli | 4 +- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/lib_validation/protocol_plugin.ml b/src/lib_validation/protocol_plugin.ml index 28d763c6d7c1..120b58d2ee9c 100644 --- a/src/lib_validation/protocol_plugin.ml +++ b/src/lib_validation/protocol_plugin.ml @@ -193,25 +193,55 @@ let validation_plugin_not_found = ~pp1:Protocol_hash.pp ("protocol_hash", Protocol_hash.encoding) +module Patch_T (Proto : T) : T = struct + include Proto + + let validate_operation ?check_signature validation_state oph op = + let open Lwt_syntax in + let* status = Proto.Plugin.syntactic_check op in + match status with + | `Ill_formed -> failwith "Ill-formed operation filtered" + | `Well_formed -> + Proto.validate_operation ?check_signature validation_state oph op + + module Plugin = struct + include Proto.Plugin + + let pre_filter info config op = + let open Lwt_syntax in + let* status = Proto.Plugin.syntactic_check op in + match status with + | `Ill_formed -> + Lwt.return + (`Refused + (Error_monad.TzTrace.make + (Error_monad.error_of_fmt "Ill-formed operation filtered"))) + | `Well_formed -> Proto.Plugin.pre_filter info config op + end +end + let proto_with_validation_plugin ~block_hash protocol_hash = let open Lwt_result_syntax in - match Protocol_hash.Table.find validation_plugin_table protocol_hash with - | Some proto_with_plugin -> return proto_with_plugin - | None -> ( - match Registered_protocol.get protocol_hash with - | None -> - tzfail - (Block_validator_errors.Unavailable_protocol - {block = block_hash; protocol = protocol_hash}) - | Some (module Proto : Registered_protocol.T) -> - let*! () = - match Proto.environment_version with - | V0 -> - (* This is normal for protocols Genesis and 000 - because they don't have a plugin. *) - Lwt.return_unit - | _ -> - Internal_event.Simple.(emit validation_plugin_not_found) - protocol_hash - in - return (module No_plugin (Proto) : T)) + let* (module Proto_with_plugin) = + match Protocol_hash.Table.find validation_plugin_table protocol_hash with + | Some proto_with_plugin -> return proto_with_plugin + | None -> ( + match Registered_protocol.get protocol_hash with + | None -> + tzfail + (Block_validator_errors.Unavailable_protocol + {block = block_hash; protocol = protocol_hash}) + | Some (module Proto : Registered_protocol.T) -> + let*! () = + match Proto.environment_version with + | V0 -> + (* This is normal for protocols Genesis and 000 + because they don't have a plugin. *) + Lwt.return_unit + | _ -> + Internal_event.Simple.(emit validation_plugin_not_found) + protocol_hash + in + return (module No_plugin (Proto) : T)) + in + return (module Patch_T (Proto_with_plugin) : T) diff --git a/src/lib_validation/protocol_plugin.mli b/src/lib_validation/protocol_plugin.mli index 73177d9b3d82..f3461dd252e0 100644 --- a/src/lib_validation/protocol_plugin.mli +++ b/src/lib_validation/protocol_plugin.mli @@ -68,7 +68,9 @@ module type T = sig To be used mostly as an exceptional mechanism to prevent ill-formed operations to block block application. - Should be called before the {!pre_filter}, does not need a context. *) + Note that the functions exposed in the output of + {!proto_with_validation_plugin} already call [syntactic_check] + when appropriate. *) val syntactic_check : operation -> [`Well_formed | `Ill_formed] Lwt.t (** Perform some light preliminary checks on the operation. -- GitLab From 4e08f34e90bb33be81f5b4cf1f37289f6cedcfb0 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Tue, 25 Jul 2023 15:50:17 +0200 Subject: [PATCH 2/4] Validation & shell: remove syntactic checks which are now redundant with the patching in protocol_plugin --- src/lib_shell/prevalidation.ml | 11 +---------- src/lib_validation/block_validation.ml | 20 ++++++-------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/lib_shell/prevalidation.ml b/src/lib_shell/prevalidation.ml index 8081b3aef73c..c369e5edd073 100644 --- a/src/lib_shell/prevalidation.ml +++ b/src/lib_shell/prevalidation.ml @@ -176,16 +176,7 @@ module MakeAbstract create_aux ~old_state chain_store head timestamp let pre_filter state (filter_config, (_ : Prevalidator_bounding.config)) op = - let open Lwt_syntax in - let* status = Proto.Plugin.syntactic_check op.protocol in - match status with - | `Ill_formed -> - Lwt.return - (`Refused - (Error_monad.TzTrace.make - (Error_monad.error_of_fmt "Ill-formed operation filtered"))) - | `Well_formed -> - Proto.Plugin.pre_filter state.plugin_info filter_config op.protocol + Proto.Plugin.pre_filter state.plugin_info filter_config op.protocol type error_classification = Prevalidator_classification.error_classification diff --git a/src/lib_validation/block_validation.ml b/src/lib_validation/block_validation.ml index c1c1fa1e7ade..73438c89e7be 100644 --- a/src/lib_validation/block_validation.ml +++ b/src/lib_validation/block_validation.ml @@ -896,16 +896,12 @@ module Make (Proto : Protocol_plugin.T) = struct {shell = op.raw.shell; protocol_data = op.protocol_data} in let open Lwt_result_syntax in - let*! status = Proto.Plugin.syntactic_check operation in let* validation_state = - match status with - | `Ill_formed -> failwith "Ill-formed operation filtered" - | `Well_formed -> - Proto.validate_operation - ~check_signature:op.check_signature - pv.validation_state - op.hash - operation + Proto.validate_operation + ~check_signature:op.check_signature + pv.validation_state + op.hash + operation in let* application_state, receipt = Proto.apply_operation pv.application_state op.hash operation @@ -1286,11 +1282,7 @@ module Make (Proto : Protocol_plugin.T) = struct (fun state ops -> List.fold_left_es (fun state (oph, op, check_signature) -> - let*! status = Proto.Plugin.syntactic_check op in - match status with - | `Ill_formed -> failwith "Ill-formed operation filtered" - | `Well_formed -> - Proto.validate_operation ~check_signature state oph op) + Proto.validate_operation ~check_signature state oph op) state ops) state -- GitLab From c6b87a375a558a67f70497988c8a4574c39f340c Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Mon, 14 Aug 2023 15:02:09 +0200 Subject: [PATCH 3/4] Validation/proto_plugin: move syntactic_check from pre_filter to Mempool.add_operation, which is a more appropriate counterpart to validation_operation --- src/lib_validation/protocol_plugin.ml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/lib_validation/protocol_plugin.ml b/src/lib_validation/protocol_plugin.ml index 120b58d2ee9c..14d32591c59d 100644 --- a/src/lib_validation/protocol_plugin.ml +++ b/src/lib_validation/protocol_plugin.ml @@ -204,19 +204,26 @@ module Patch_T (Proto : T) : T = struct | `Well_formed -> Proto.validate_operation ?check_signature validation_state oph op - module Plugin = struct - include Proto.Plugin + module Mempool = struct + include Proto.Mempool - let pre_filter info config op = + let add_operation ?check_signature ?conflict_handler validation_info + mempool_state (oph, op) = let open Lwt_syntax in let* status = Proto.Plugin.syntactic_check op in match status with | `Ill_formed -> - Lwt.return - (`Refused - (Error_monad.TzTrace.make - (Error_monad.error_of_fmt "Ill-formed operation filtered"))) - | `Well_formed -> Proto.Plugin.pre_filter info config op + Lwt.return_error + (Proto.Mempool.Validation_error + (TzTrace.make + (Error_monad.error_of_fmt "Ill-formed operation filtered"))) + | `Well_formed -> + Proto.Mempool.add_operation + ?check_signature + ?conflict_handler + validation_info + mempool_state + (oph, op) end end -- GitLab From 43579fb2c13c6dc2e071189d534589dccf8c0269 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Mon, 14 Aug 2023 16:19:32 +0200 Subject: [PATCH 4/4] Validation/protocol_plugin: define a specific error because Error_monad.Exn is `Temporary so it would cause ill-formed operations to be validated again with each new head, which we don't want. --- src/lib_validation/protocol_plugin.ml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lib_validation/protocol_plugin.ml b/src/lib_validation/protocol_plugin.ml index 14d32591c59d..66cb80a08ae3 100644 --- a/src/lib_validation/protocol_plugin.ml +++ b/src/lib_validation/protocol_plugin.ml @@ -193,6 +193,24 @@ let validation_plugin_not_found = ~pp1:Protocol_hash.pp ("protocol_hash", Protocol_hash.encoding) +type error += Ill_formed_operation of Operation_hash.t + +let () = + register_error_kind + `Permanent + ~id:"validation.plugin.ill_formed_operation" + ~title:"Ill_formed_operation" + ~description:"Ill-formed operation filtered" + ~pp:(fun ppf oph -> + Format.fprintf + ppf + "Ill-formed operation filtered: %a." + Operation_hash.pp + oph) + Data_encoding.(obj1 (req "operation_hash" Operation_hash.encoding)) + (function Ill_formed_operation oph -> Some oph | _ -> None) + (fun oph -> Ill_formed_operation oph) + module Patch_T (Proto : T) : T = struct include Proto @@ -200,7 +218,7 @@ module Patch_T (Proto : T) : T = struct let open Lwt_syntax in let* status = Proto.Plugin.syntactic_check op in match status with - | `Ill_formed -> failwith "Ill-formed operation filtered" + | `Ill_formed -> Lwt_result_syntax.tzfail (Ill_formed_operation oph) | `Well_formed -> Proto.validate_operation ?check_signature validation_state oph op @@ -215,8 +233,7 @@ module Patch_T (Proto : T) : T = struct | `Ill_formed -> Lwt.return_error (Proto.Mempool.Validation_error - (TzTrace.make - (Error_monad.error_of_fmt "Ill-formed operation filtered"))) + (TzTrace.make (Ill_formed_operation oph))) | `Well_formed -> Proto.Mempool.add_operation ?check_signature -- GitLab