(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2020 Metastate AG *) (* *) (* 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. *) (* *) (*****************************************************************************) (***************** Prevalidation errors ***********************************) type error += Parse_error type error += Too_many_operations type error += Oversized_operation of {size : int; max : int} type error += | Future_block_header of { block : Block_hash.t; block_time : Time.Protocol.t; time : Time.System.t; } type error += Cannot_serialize_operation_metadata let () = (* Parse error *) register_error_kind `Permanent ~id:"node.prevalidation.parse_error" ~title:"Parsing error in prevalidation" ~description: "Raised when an operation has not been parsed correctly during \ prevalidation." ~pp:(fun ppf () -> Format.fprintf ppf "Operation parsing error in prevalidation.") Data_encoding.empty (function Parse_error -> Some () | _ -> None) (fun () -> Parse_error) ; (* Too many operations *) register_error_kind `Temporary ~id:"node.prevalidation.too_many_operations" ~title:"Too many pending operations in prevalidation" ~description:"The prevalidation context is full." ~pp:(fun ppf () -> Format.fprintf ppf "Too many operations in prevalidation context.") Data_encoding.empty (function Too_many_operations -> Some () | _ -> None) (fun () -> Too_many_operations) ; (* Oversized operation *) register_error_kind `Permanent ~id:"node.prevalidation.oversized_operation" ~title:"Oversized operation" ~description:"The operation size is bigger than allowed." ~pp:(fun ppf (size, max) -> Format.fprintf ppf "Oversized operation (size: %d, max: %d)" size max) Data_encoding.(obj2 (req "size" int31) (req "max_size" int31)) (function Oversized_operation {size; max} -> Some (size, max) | _ -> None) (fun (size, max) -> Oversized_operation {size; max}) ; (* Block from the future *) register_error_kind `Temporary ~id:"node.prevalidation.future_block_header" ~title:"Future block header" ~description:"The block was annotated with a time too far in the future." ~pp:(fun ppf (block, block_time, time) -> Format.fprintf ppf "Future block header (block: %a, block_time: %a, time: %a)" Block_hash.pp block Time.System.pp_hum (Time.System.of_protocol_exn block_time) Time.System.pp_hum time) Data_encoding.( obj3 (req "block" Block_hash.encoding) (req "block_time" Time.Protocol.encoding) (req "time" Time.System.encoding)) (function | Future_block_header {block; block_time; time} -> Some (block, block_time, time) | _ -> None) (fun (block, block_time, time) -> Future_block_header {block; block_time; time}) ; Error_monad.register_error_kind `Permanent ~id:"block_validation.cannot_serialize_metadata" ~title:"Cannot serialize metadata" ~description:"Unable to serialize metadata" ~pp:(fun ppf () -> Format.fprintf ppf "Unable to serialize the metadata for an operation.") Data_encoding.empty (function Cannot_serialize_operation_metadata -> Some () | _ -> None) (fun () -> Cannot_serialize_operation_metadata) (************************* State errors ***********************************) type error += Unknown_chain of Chain_id.t type error += Bad_data_dir type error += Block_not_invalid of Block_hash.t let () = (* Unknown network *) register_error_kind `Permanent ~id:"node.state.unknown_chain" ~title:"Unknown chain" ~description: "The chain identifier could not be found in the chain identifiers table." ~pp:(fun ppf id -> Format.fprintf ppf "Unknown chain %a" Chain_id.pp id) Data_encoding.(obj1 (req "chain" Chain_id.encoding)) (function Unknown_chain x -> Some x | _ -> None) (fun x -> Unknown_chain x) ; register_error_kind `Permanent ~id:"node.state.bad_data_dir" ~title:"Bad data directory" ~description: "The data directory could not be read. This could be because it was \ generated with an old version of the tezos-node program. Deleting and \ regenerating this directory may fix the problem." ~pp:(fun ppf () -> Format.fprintf ppf "Bad data directory.") Data_encoding.empty (function Bad_data_dir -> Some () | _ -> None) (fun () -> Bad_data_dir) ; (* Block not invalid *) register_error_kind `Permanent ~id:"node.state.block_not_invalid" ~title:"Block not invalid" ~description:"The invalid block to be unmarked was not actually invalid." ~pp:(fun ppf block -> Format.fprintf ppf "Block %a was expected to be invalid, but was not actually invalid." Block_hash.pp block) Data_encoding.(obj1 (req "block" Block_hash.encoding)) (function Block_not_invalid block -> Some block | _ -> None) (fun block -> Block_not_invalid block) (* Block database error *) type error += Inconsistent_hash of Context_hash.t * Context_hash.t type error += Missing_block_metadata_hash of Block_hash.t type error += Missing_operation_metadata_hashes of Block_hash.t let () = (* Inconsistent hash *) register_error_kind `Permanent ~id:"node.state.block.inconsistent_context_hash" ~title:"Inconsistent commit hash" ~description: "When committing the context of a block, the announced context hash was \ not the one computed at commit time." ~pp:(fun ppf (got, exp) -> Format.fprintf ppf "@[Inconsistent hash:@ got: %a@ expected: %a" Context_hash.pp got Context_hash.pp exp) Data_encoding.( obj2 (req "wrong_context_hash" Context_hash.encoding) (req "expected_context_hash" Context_hash.encoding)) (function Inconsistent_hash (got, exp) -> Some (got, exp) | _ -> None) (fun (got, exp) -> Inconsistent_hash (got, exp)) ; register_error_kind `Permanent ~id:"node.state.block.missing_block_metadata_hash" ~title:"Missing block metadata hash" ~description: "A block was expected to commit to a block metadata hash, however none \ was given." ~pp:(fun ppf block -> Format.fprintf ppf "@[Missing block metadata hash at block: %a" Block_hash.pp block) Data_encoding.(obj1 (req "block" Block_hash.encoding)) (function Missing_block_metadata_hash block -> Some block | _ -> None) (fun block -> Missing_block_metadata_hash block) ; register_error_kind `Permanent ~id:"node.state.block.missing_operation_metadata_hashes" ~title:"Missing operation metadata hashes" ~description: "A block was expected to commit to operation metadata hashes, however \ none were given." ~pp:(fun ppf block -> Format.fprintf ppf "@[Missing operation metadata hashes at block: %a" Block_hash.pp block) Data_encoding.(obj1 (req "block" Block_hash.encoding)) (function | Missing_operation_metadata_hashes block -> Some block | _ -> None) (fun block -> Missing_operation_metadata_hashes block) (******************* Bootstrap pipeline errors ****************************) type error += Invalid_locator of P2p_peer.Id.t * Block_locator.t type error += Too_short_locator of P2p_peer.Id.t * Block_locator.t let () = (* Invalid locator *) register_error_kind `Permanent ~id:"node.bootstrap_pipeline.invalid_locator" ~title:"Invalid block locator" ~description:"Block locator is invalid." ~pp:(fun ppf (id, locator) -> Format.fprintf ppf "Invalid block locator on peer %a:\n%a" P2p_peer.Id.pp id Block_locator.pp locator) Data_encoding.( obj2 (req "id" P2p_peer.Id.encoding) (req "locator" Block_locator.encoding)) (function Invalid_locator (id, loc) -> Some (id, loc) | _ -> None) (fun (id, loc) -> Invalid_locator (id, loc)) ; (* Too short locator *) register_error_kind `Permanent ~id:"node.bootstrap_pipeline.too_short_locator" ~title:"Too short locator" ~description:"Block locator is too short." ~pp:(fun ppf (id, locator) -> Format.fprintf ppf "Too short locator on peer %a:\n%a" P2p_peer.Id.pp id Block_locator.pp locator) Data_encoding.( obj2 (req "id" P2p_peer.Id.encoding) (req "locator" Block_locator.encoding)) (function Too_short_locator (id, loc) -> Some (id, loc) | _ -> None) (fun (id, loc) -> Too_short_locator (id, loc)) (******************* Protocol validator errors ****************************) type protocol_error = Compilation_failed | Dynlinking_failed type error += | Invalid_protocol of {hash : Protocol_hash.t; error : protocol_error} let protocol_error_encoding = let open Data_encoding in union [ case (Tag 0) ~title:"Compilation failed" (obj1 (req "error" (constant "compilation_failed"))) (function Compilation_failed -> Some () | _ -> None) (fun () -> Compilation_failed); case (Tag 1) ~title:"Dynlinking failed" (obj1 (req "error" (constant "dynlinking_failed"))) (function Dynlinking_failed -> Some () | _ -> None) (fun () -> Dynlinking_failed); ] let pp_protocol_error ppf = function | Compilation_failed -> Format.fprintf ppf "compilation error" | Dynlinking_failed -> Format.fprintf ppf "dynlinking error" let () = (* Invalid protocol *) register_error_kind `Permanent ~id:"node.protocol_validator.invalid_protocol" ~title:"Invalid protocol" ~description:"Invalid protocol." ~pp:(fun ppf (protocol, error) -> Format.fprintf ppf "@[Invalid protocol %a@ %a@]" Protocol_hash.pp_short protocol pp_protocol_error error) Data_encoding.( merge_objs (obj1 (req "invalid_protocol" Protocol_hash.encoding)) protocol_error_encoding) (function | Invalid_protocol {hash; error} -> Some (hash, error) | _ -> None) (fun (hash, error) -> Invalid_protocol {hash; error}) type error += Cannot_load_protocol of Protocol_hash.t let () = register_error_kind `Permanent ~id:"node.protocol_validator.cannot_load_protocol" ~title:"Cannot load protocol" ~description:"Cannot load protocol from disk" ~pp:(fun ppf protocol -> Format.fprintf ppf "Failed to load the protocol %a from disk: the corresponding files \ might be missing or corrupted." Protocol_hash.pp protocol) Data_encoding.(obj1 (req "protocol" Protocol_hash.encoding)) (function Cannot_load_protocol protocol -> Some protocol | _ -> None) (fun protocol -> Cannot_load_protocol protocol) (********************* Peer validator errors ******************************) type error += Unknown_ancestor | Known_invalid let () = (* Unknown ancestor *) register_error_kind `Permanent ~id:"node.peer_validator.unknown_ancestor" ~title:"Unknown ancestor" ~description:"Unknown ancestor block found in the peer's chain" ~pp:(fun ppf () -> Format.fprintf ppf "Unknown ancestor") Data_encoding.empty (function Unknown_ancestor -> Some () | _ -> None) (fun () -> Unknown_ancestor) ; (* Known invalid *) register_error_kind `Permanent ~id:"node.peer_validator.known_invalid" ~title:"Known invalid" ~description:"Known invalid block found in the peer's chain" ~pp:(fun ppf () -> Format.fprintf ppf "Known invalid") Data_encoding.empty (function Known_invalid -> Some () | _ -> None) (fun () -> Known_invalid) (************************ Validator errors ********************************) type error += Inactive_chain of Chain_id.t type error += Checkpoint_error of Block_hash.t * P2p_peer.Id.t option let () = (* Inactive network *) register_error_kind `Branch ~id:"node.validator.inactive_chain" ~title:"Inactive chain" ~description:"Attempted validation of a block from an inactive chain." ~pp:(fun ppf chain -> Format.fprintf ppf "Tried to validate a block from chain %a, that is not currently \ considered active." Chain_id.pp chain) Data_encoding.(obj1 (req "inactive_chain" Chain_id.encoding)) (function Inactive_chain chain -> Some chain | _ -> None) (fun chain -> Inactive_chain chain) ; register_error_kind `Branch ~id:"node.validator.checkpoint_error" ~title:"Block incompatible with the current checkpoint." ~description: "The block belongs to a branch that is not compatible with the current \ checkpoint." ~pp:(fun ppf (block, peer) -> match peer with | None -> Format.fprintf ppf "The block %a is incompatible with the current checkpoint." Block_hash.pp_short block | Some peer -> Format.fprintf ppf "The peer %a send us a block which is a sibling of the configured \ checkpoint (%a)." P2p_peer.Id.pp peer Block_hash.pp_short block) Data_encoding.( obj2 (req "block" Block_hash.encoding) (opt "peer" P2p_peer.Id.encoding)) (function | Checkpoint_error (block, peer) -> Some (block, peer) | _ -> None) (fun (block, peer) -> Checkpoint_error (block, peer))