diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b251896f1100d317f212583d03d7c9e87e34d8ab..6fef43edc81dbd0cd6fc0a50c109cedca02639bc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -398,126 +398,131 @@ opam:38:tezos-protocol-genesis: variables: package: tezos-protocol-genesis -opam:39:ocplib-resto-json: - <<: *opam_definition - variables: - package: ocplib-resto-json - -opam:40:tezos-protocol-updater: +opam:39:tezos-protocol-updater: <<: *opam_definition variables: package: tezos-protocol-updater -opam:41:tezos-p2p: +opam:40:tezos-p2p: <<: *opam_definition variables: package: tezos-p2p -opam:42:tezos-baking-alpha-commands: +opam:41:ocplib-resto-json: <<: *opam_definition variables: - package: tezos-baking-alpha-commands + package: ocplib-resto-json -opam:43:tezos-client-alpha-commands: +opam:42:tezos-baking-alpha-commands: <<: *opam_definition variables: - package: tezos-client-alpha-commands + package: tezos-baking-alpha-commands -opam:44:tezos-client-base-unix: +opam:43:tezos-client-base-unix: <<: *opam_definition variables: package: tezos-client-base-unix -opam:45:tezos-client-genesis: +opam:44:tezos-client-genesis: <<: *opam_definition variables: package: tezos-client-genesis -opam:46:ocplib-ezresto: - <<: *opam_definition - variables: - package: ocplib-ezresto - -opam:47:tezos-embedded-protocol-alpha: +opam:45:tezos-embedded-protocol-alpha: <<: *opam_definition variables: package: tezos-embedded-protocol-alpha -opam:48:tezos-embedded-protocol-demo: +opam:46:tezos-embedded-protocol-demo: <<: *opam_definition variables: package: tezos-embedded-protocol-demo -opam:49:tezos-embedded-protocol-genesis: +opam:47:tezos-embedded-protocol-genesis: <<: *opam_definition variables: package: tezos-embedded-protocol-genesis -opam:50:tezos-shell: +opam:48:tezos-shell: <<: *opam_definition variables: package: tezos-shell -opam:51:tezos-endorser-alpha-commands: +opam:49:tezos-client-alpha-commands: <<: *opam_definition variables: - package: tezos-endorser-alpha-commands + package: tezos-client-alpha-commands -opam:52:tezos-client: +opam:50:ocplib-ezresto: <<: *opam_definition variables: - package: tezos-client + package: ocplib-ezresto -opam:53:ocplib-ezresto-directory: +opam:51:tezos-baking-alpha-services: <<: *opam_definition variables: - package: ocplib-ezresto-directory + package: tezos-baking-alpha-services -opam:54:tezos-accuser-alpha: +opam:52:tezos-accuser-alpha: <<: *opam_definition variables: package: tezos-accuser-alpha -opam:55:tezos-endorser-alpha: +opam:53:tezos-baker-alpha: <<: *opam_definition variables: - package: tezos-endorser-alpha + package: tezos-baker-alpha -opam:56:tezos-accuser-alpha-commands: +opam:54:ocplib-json-typed-browser: <<: *opam_definition variables: - package: tezos-accuser-alpha-commands + package: ocplib-json-typed-browser -opam:57:tezos-baker-alpha: +opam:55:tezos-protocol-demo: <<: *opam_definition variables: - package: tezos-baker-alpha + package: tezos-protocol-demo -opam:58:tezos-protocol-demo: +opam:56:tezos-node: <<: *opam_definition variables: - package: tezos-protocol-demo + package: tezos-node -opam:59:tezos-signer: +opam:57:tezos-signer: <<: *opam_definition variables: package: tezos-signer -opam:60:tezos-node: +opam:58:tezos-endorser-alpha-commands: <<: *opam_definition variables: - package: tezos-node + package: tezos-endorser-alpha-commands -opam:61:ocplib-json-typed-browser: +opam:59:tezos-client: <<: *opam_definition variables: - package: ocplib-json-typed-browser + package: tezos-client + +opam:60:tezos-endorser-alpha: + <<: *opam_definition + variables: + package: tezos-endorser-alpha + +opam:61:tezos-accuser-alpha-commands: + <<: *opam_definition + variables: + package: tezos-accuser-alpha-commands opam:62:tezos-baker-alpha-commands: <<: *opam_definition variables: package: tezos-baker-alpha-commands +opam:63:ocplib-ezresto-directory: + <<: *opam_definition + variables: + package: ocplib-ezresto-directory + ##END_OPAM## diff --git a/src/proto_alpha/lib_client/client_proto_args.ml b/src/proto_alpha/lib_client/client_proto_args.ml index 4a6f4dfe45fcf7b3a07861439a029fe9acf44da3..4f7f13a676ef3424c341e25277163189cfc92ab1 100644 --- a/src/proto_alpha/lib_client/client_proto_args.ml +++ b/src/proto_alpha/lib_client/client_proto_args.ml @@ -333,4 +333,35 @@ module Daemon = struct ~long:"denunciation" ~short:'D' ~doc:"run the denunciation daemon" () + let monitor_switch = + switch + ~long:"monitor" + ~short:'M' + ~doc:"run an RPC server to allow monitoring the daemon" () + let monitor_port default_port = + default_arg + ~long:"monitor-port" + ~doc:"port to run the daemon's monitoring RPC server on" + ~placeholder:"port" + ~default:(string_of_int default_port) + (parameter (fun _ s -> return s)) + let monitor_host = + default_arg + ~long:"monitor-host" + ~doc:"host address for the daemon's monitoring RPC server to listen on" + ~placeholder:"host" + ~default:"" + (parameter (fun _ s -> return s)) + let monitor_cert = + arg + ~long:"monitor-cert" + ~doc:"have the daemon's monitoring RPC server use TLS with the given certificate" + ~placeholder:"file" + (parameter (fun _ s -> return s)) + let monitor_key = + arg + ~long:"monitor-key" + ~doc:"have the daemon's monitoring RPC server use TLS with the given key" + ~placeholder:"file" + (parameter (fun _ s -> return s)) end diff --git a/src/proto_alpha/lib_client/client_proto_args.mli b/src/proto_alpha/lib_client/client_proto_args.mli index a2208c14d06595ff63883304cc96075b80118b56..7f863b5f98fe2a8dd00f26a5e5e560aee2549391 100644 --- a/src/proto_alpha/lib_client/client_proto_args.mli +++ b/src/proto_alpha/lib_client/client_proto_args.mli @@ -65,6 +65,11 @@ module Daemon : sig val baking_switch: (bool, Proto_alpha.full) Clic.arg val endorsement_switch: (bool, Proto_alpha.full) Clic.arg val denunciation_switch: (bool, Proto_alpha.full) Clic.arg + val monitor_switch: (bool, Proto_alpha.full) Clic.arg + val monitor_port: int -> (string, Proto_alpha.full) Clic.arg + val monitor_host: (string, Proto_alpha.full) Clic.arg + val monitor_cert: (string option, Proto_alpha.full) Clic.arg + val monitor_key: (string option, Proto_alpha.full) Clic.arg end val string_parameter : (string, full) Clic.parameter diff --git a/src/proto_alpha/lib_delegate/client_baking_blocks.ml b/src/proto_alpha/lib_delegate/client_baking_blocks.ml index d40cc2c55b2d681cc1d9fc3854323c7093448312..dbaad5f63c2edb39a1a015d07f8b06e33ea764d6 100644 --- a/src/proto_alpha/lib_delegate/client_baking_blocks.ml +++ b/src/proto_alpha/lib_delegate/client_baking_blocks.ml @@ -61,19 +61,22 @@ let info cctxt ?(chain = `Main) block = cctxt ~chain ~block () >>=? fun shell_header -> raw_info cctxt ~chain hash shell_header -let monitor_valid_blocks cctxt ?chains ?protocols ~next_protocols () = +let monitor_valid_blocks cctxt ?(report=ignore) ?chains ?protocols ~next_protocols () = Monitor_services.valid_blocks cctxt ?chains ?protocols ?next_protocols () >>=? fun (block_stream, _stop) -> return (Lwt_stream.map_s - (fun ((chain, block), { Tezos_base.Block_header.shell }) -> - raw_info cctxt ~chain:(`Hash chain) block shell) + (fun ((chain, block), data) -> + report (block, data) ; + raw_info cctxt ~chain:(`Hash chain) block data.Tezos_base.Block_header.shell) block_stream) -let monitor_heads cctxt ~next_protocols chain = +let monitor_heads cctxt ?(report=ignore) ~next_protocols chain = Monitor_services.heads cctxt ?next_protocols chain >>=? fun (block_stream, _stop) -> return (Lwt_stream.map_s - (fun (block, { Tezos_base.Block_header.shell }) -> raw_info cctxt ~chain block shell) + (fun (block, data) -> + report (block, data) ; + raw_info cctxt ~chain block data.Tezos_base.Block_header.shell) block_stream) let blocks_from_current_cycle cctxt ?(chain = `Main) block ?(offset = 0l) () = diff --git a/src/proto_alpha/lib_delegate/client_baking_blocks.mli b/src/proto_alpha/lib_delegate/client_baking_blocks.mli index b92795bda58117dcf6dbeb19615c37a1dbf18f78..4d988ac7cb1036a3118d3fd3058ab701c632a729 100644 --- a/src/proto_alpha/lib_delegate/client_baking_blocks.mli +++ b/src/proto_alpha/lib_delegate/client_baking_blocks.mli @@ -47,6 +47,7 @@ val info: val monitor_valid_blocks: #Proto_alpha.rpc_context -> + ?report:(Block_hash.t * Tezos_base.Block_header.t -> unit) -> ?chains:Chain_services.chain list -> ?protocols:Protocol_hash.t list -> next_protocols:Protocol_hash.t list option -> @@ -54,6 +55,7 @@ val monitor_valid_blocks: val monitor_heads: #Proto_alpha.rpc_context -> + ?report:(Block_hash.t * Tezos_base.Block_header.t -> unit) -> next_protocols:Protocol_hash.t list option -> Chain_services.chain -> block_info tzresult Lwt_stream.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml index 6b00e84b934907c0d6cde6e5c513bd82028c139c..162cc49682ff55c8168619ae1f945bb2209743bd 100644 --- a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml +++ b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml @@ -113,6 +113,7 @@ let process_endorsements (cctxt : #Proto_alpha.full) state ~chain lwt_log_notice Tag.DSL.(fun f -> f "Double endorsement evidence injected %a" -% t event "double_endorsement_denounced" + -% t signed_operation_tag bytes -% a Operation_hash.Logging.tag op_hash) >>= fun () -> return @@ HLevel.replace state.endorsements_table level (Delegate_Map.add delegate new_endorsement map) @@ -166,6 +167,7 @@ let process_block (cctxt : #Proto_alpha.full) state ~chain (header : Alpha_block lwt_log_notice Tag.DSL.(fun f -> f "Double baking evidence injected %a" -% t event "double_baking_denounced" + -% t signed_operation_tag bytes -% a Operation_hash.Logging.tag op_hash) >>= fun () -> return @@ HLevel.replace state.blocks_table level (Delegate_Map.add baker hash map) diff --git a/src/proto_alpha/lib_delegate/client_baking_endorsement.ml b/src/proto_alpha/lib_delegate/client_baking_endorsement.ml index 4759717a5b86ef27ecaba2090c450330e08d386f..f899677da374201a67ed481da32b3f711a55da42 100644 --- a/src/proto_alpha/lib_delegate/client_baking_endorsement.ml +++ b/src/proto_alpha/lib_delegate/client_baking_endorsement.ml @@ -137,6 +137,7 @@ let endorse_for_delegate cctxt block delegate = -% a Block_hash.Logging.tag hash -% a level_tag level -% s Client_keys.Logging.tag name + -% t Signature.Public_key_hash.Logging.tag delegate -% a Operation_hash.Logging.tag oph) >>= fun () -> return_unit diff --git a/src/proto_alpha/lib_delegate/client_baking_forge.ml b/src/proto_alpha/lib_delegate/client_baking_forge.ml index 6a891b8d77f6e95eb229962cf1122451923f9b9f..69500e9f1ef7b2cb743263594e3984bc4e8a63e1 100644 --- a/src/proto_alpha/lib_delegate/client_baking_forge.ml +++ b/src/proto_alpha/lib_delegate/client_baking_forge.ml @@ -135,6 +135,12 @@ let inject_block src_sk shell_header priority seed_nonce_hash >>=? fun signed_header -> Shell_services.Injection.block cctxt ?force ~chain signed_header operations >>=? fun block_hash -> + lwt_log_info Tag.DSL.(fun f -> + f "Client_baking_forge.inject_block: inject %a" + -% t event "inject_baked_block" + -% a Block_hash.Logging.tag block_hash + -% t signed_header_tag signed_header + -% t operations_tag operations) >>= fun () -> return block_hash type error += diff --git a/src/proto_alpha/lib_delegate/client_baking_revelation.ml b/src/proto_alpha/lib_delegate/client_baking_revelation.ml index 30b03e4385d5cb646eab1bef9b95427a6848f01c..03a2611ee711c2b23157898d2f642bfa63674c3c 100644 --- a/src/proto_alpha/lib_delegate/client_baking_revelation.ml +++ b/src/proto_alpha/lib_delegate/client_baking_revelation.ml @@ -34,7 +34,16 @@ let inject_seed_nonce_revelation rpc_config ?(chain = `Main) block ?async nonces Alpha_services.Forge.seed_nonce_revelation rpc_config (chain, block) ~branch ~level ~nonce () >>=? fun bytes -> let bytes = Signature.concat bytes Signature.zero in - Shell_services.Injection.operation rpc_config ?async ~chain bytes) + Shell_services.Injection.operation rpc_config ?async ~chain bytes >>=? fun oph -> + lwt_debug Tag.DSL.(fun f -> + f "Revealing nonce %a from level %a at chain %a, block %a with operation %a" + -% t event "reveal_nonce" + -% a Logging.nonce_tag nonce + -% a Logging.level_tag level + -% a Logging.chain_tag chain + -% a Logging.block_tag block + -% a Operation_hash.Logging.tag oph) >>= fun () -> + return oph) nonces >>=? fun ophs -> return ophs diff --git a/src/proto_alpha/lib_delegate/client_baking_rpc.ml b/src/proto_alpha/lib_delegate/client_baking_rpc.ml new file mode 100644 index 0000000000000000000000000000000000000000..e9d3814dae9b3612eddd3ab31ffbd35d1b1eb638 --- /dev/null +++ b/src/proto_alpha/lib_delegate/client_baking_rpc.ml @@ -0,0 +1,465 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open RPC_logging +open Tezos_baking_alpha_services +open Tezos_baking_alpha_services.Event_queues + +type error += RPC_Port_already_in_use of P2p_point.Id.t list +type error += Bad_TLS_config of unit + +let () = + register_error_kind + `Permanent + ~id:"main.run.port_already_in_use" + ~title:"Cannot start daemon: RPC port already in use" + ~description:"Another tezos client is probably running on the same RPC port." + ~pp:begin fun ppf addrlist -> + Format.fprintf ppf + "Another tezos client is probably running on one of these addresses (%a). \ + Please choose another RPC port." + (Format.pp_print_list P2p_point.Id.pp) addrlist + end + Data_encoding.(obj1 (req "addrlist" (list P2p_point.Id.encoding))) + (function | RPC_Port_already_in_use addrlist -> Some addrlist | _ -> None) + (fun addrlist -> RPC_Port_already_in_use addrlist) + ; + register_error_kind + `Permanent + ~id:"main.run.bad_tls_config" + ~title:"Cannot start daemon: Must provide both key and certificate for TLS." + ~description:"" + ~pp:begin fun ppf _ -> + Format.fprintf ppf + "Full TLS configuration for the RPC listener was not provided. Both a \ + key file and certificate file are required." + end + Data_encoding.empty + (function | Bad_TLS_config () -> Some () | _ -> None) + (fun () -> Bad_TLS_config ()) + +type rpc = { + listen_host : string ; + listen_port : string ; + cors_origins : string list ; + cors_headers : string list ; + tls : tls option ; +} + +and tls = { + cert : string ; + key : string ; +} + +let default_rpc = { + listen_host = "" ; + listen_port = "" ; + cors_origins = [] ; + cors_headers = [] ; + tls = None ; +} + +let resolve_addr ?default_port ?(passive = false) host port = + let node = if host = "_" then "" else host + and service = + match port, default_port with + | "", None -> + invalid_arg "" + | "", Some default_port -> string_of_int default_port + | port, _ -> port in + Lwt_utils_unix.getaddrinfo ~passive ~node ~service + +let resolve_rpc_listening_addrs host port = + resolve_addr + ~passive:true + host + port + +module type QUEUES = sig + type feeders +end + +module Queues_private = struct + + (** Type of a set of event queues. *) + module type T = sig + include Queues_svc.T + + (** Internal state of the queues. *) + type state + + (** Create a new set of queues of this shape. *) + val create : unit -> state + + (** Output the log of events for each queue. *) + val answer : state -> output + type feeders + + (** Return a set of functions. Typically, each one feeds + * events into a single queue. + *) + val feeders : state -> feeders + + (** Return a set of functions of the same shape as [feeders], + * but which don't do anything. Useful for when you don't + * want to run monitoring. + *) + val null_feeders : feeders + end + + module Nil = struct + include Queues_svc.Nil + type state = unit + let create () = () + let answer () = () + type feeders = unit + let feeders () = () + let null_feeders = () + end + + module Cons (E: EVENT)(QS: T): T + with type output = Queues_svc.Cons(E)(QS).output + and type feeders = (string -> E.t -> unit) * QS.feeders = + struct + include Queues_svc.Cons(E)(QS) + + type event = int * Time.t * string * E.t + + type state = { + stream : event Lwt_stream.t ; + push : event option -> unit ; + buffer : event Ring.t ; + seq : int ref ; + rest : QS.state ; + } + + let create () = + (* For the new queue, we have a stream to push + * events into from other logical threads, plus + * a ring buffer to serve as a bounded log. + * Events pushed onto the stream are + * automatically pulled off and placed in the + * ring buffer. + * + * Additionally, we wrap up a state that manages + * the rest of the queues. + *) + let stream, push = Lwt_stream.create () in + let buffer = Ring.create E.capacity in + let seq = ref 0 in + let rest = QS.create () in + begin + Lwt.ignore_result (Lwt_stream.iter (Ring.add buffer) stream) ; + { seq ; stream ; push ; buffer ; rest } + end + + let answer st = + (Ring.elements st.buffer, QS.answer st.rest) + + type feeders = (string -> E.t -> unit) * QS.feeders + + let feeders { push ; seq ; rest } = + let my_feeder = fun worker details -> + let time = Time.now () in + begin + seq := !seq + 1; + push (Some (!seq, time, worker, details)); + end + in (my_feeder, QS.feeders rest) + + let null_feeders = (fun _ _ -> ()), QS.null_feeders + end + +end + +open Queues_private + +module Common_queues = + Cons(Error_event)( + Cons(Block_event)( + Nil)) + +(** Wrapper for common events plus one other event. + * This only exists to convert the [feeders] type + * from a nested tuple to a record, allowing the + * corresponding daemon to refer to queues in a + * logical way. +*) +module Single_action_queues(Event: EVENT) = struct + module Raw = Cons(Event)(Common_queues) + + type output = Raw.output + type state = Raw.state + type feeders = { + action: string -> Event.t -> unit ; + error: string -> Error_event.t -> unit ; + block: string -> Block_event.t -> unit ; + } + + let output_encoding = Raw.output_encoding + let create = Raw.create + let answer = Raw.answer + + let feeders st = match Raw.feeders st with + | (action, (error, (block, ()))) -> { action ; error ; block } + + let null_feeders : feeders = { + action = (fun _ _ -> ()) ; + error = (fun _ _ -> ()) ; + block = (fun _ _ -> ()) ; + } +end + +module Baker_queues = struct + module Raw = Cons(Baked_event)(Cons(Revelation_event)(Common_queues)) + + type output = Raw.output + type state = Raw.state + type feeders = { + action: string -> Baked_event.t -> unit ; + revelation: string -> Revelation_event.t -> unit; + error: string -> Error_event.t -> unit; + block: string -> Block_event.t -> unit ; + } + + let output_encoding = Raw.output_encoding + let create = Raw.create + let answer = Raw.answer + + let feeders st = match Raw.feeders st with + | (action, (revelation, (error, (block, ())))) -> { action ; revelation ; error ; block } + + let null_feeders : feeders = { + action = (fun _ _ -> ()) ; + revelation = (fun _ _ -> ()) ; + error = (fun _ _ -> ()) ; + block = (fun _ _ -> ()) ; + } +end + +module Endorser_queues = Single_action_queues(Endorsement_event) +module Accuser_queues = Single_action_queues(Accusation_event) + +module Event_server_type(Queues: QUEUES) = struct + module type T = sig + type t = { + report : Queues.feeders ; + launch : unit Lwt.t ; + } + + val monitoring: + #Client_context.wallet -> + string list -> + Signature.public_key_hash list -> + Uri.t -> + rpc option -> + t tzresult Lwt.t + end +end + +module Event_server(Queues: Queues_private.T) = struct + + module Services = Daemon_services.Make(Queues) + + type t = { + report : Queues.feeders ; + launch : unit Lwt.t ; + } + + type node = { + config_catalog: Config_catalog.t ; + queue_state: Queues.state ; + } + + let list_events node () () = + RPC_answer.return (node.config_catalog.start_time, Queues.answer node.queue_state) + + let show_config cctxt node () () = + match node.config_catalog.delegates with + | _ :: _ -> return node.config_catalog + | [] -> Client_keys.get_keys cctxt >>=? fun keys -> + return + { node.config_catalog + with delegates = List.map (fun (_,pk,_,_) -> pk) keys } + + let build_rpc_directory cctxt node = + let dir = RPC_directory.empty in + let dir = + RPC_directory.gen_register0 dir Services.S.events + (list_events node) in + let dir = + RPC_directory.register0 dir Services.S.config + (show_config cctxt node) in + let dir = + let implementation () () = + return Data_encoding.Json.(schema Error_monad.error_encoding) in + RPC_directory.register0 dir RPC_service.error_service implementation in + let dir = + RPC_directory.register_describe_directory_service + dir RPC_service.description_service in + dir + + let init_rpc cctxt (rpc_config: rpc) node = + resolve_rpc_listening_addrs rpc_config.listen_host rpc_config.listen_port >>= function + | [] -> + failwith "Cannot resolve listening address: %S:%S" rpc_config.listen_host rpc_config.listen_port + | (addr, port) :: _ -> + let host = Ipaddr.V6.to_string addr in + let dir = build_rpc_directory cctxt node in + let mode = + match rpc_config.tls with + | None -> `TCP (`Port port) + | Some { cert ; key } -> + `TLS (`Crt_file_path cert, `Key_file_path key, + `No_password, `Port port) in + lwt_log_notice + "Starting the RPC server listening on port %d%s." + port + (if rpc_config.tls = None then "" else " (TLS enabled)") >>= fun () -> + Lwt.catch + (fun () -> + RPC_server.launch ~host mode dir + ~media_types:Media_type.all_media_types + ~cors:{ allowed_origins = rpc_config.cors_origins ; + allowed_headers = rpc_config.cors_headers } >>= fun server -> + return (Some server)) + (function + |Unix.Unix_error(Unix.EADDRINUSE, "bind","") -> + fail (RPC_Port_already_in_use [(addr,port)]) + | exn -> Lwt.return (error_exn exn) + ) + + let new_node workers delegates node_uri = return { config_catalog = { start_time = Time.now () ; workers ; delegates ; node_uri } ; queue_state = Queues.create () } + + let run cctxt workers delegates node_uri (config: rpc) = + new_node workers delegates node_uri >>=? fun node -> + init_rpc cctxt config node >>=? fun rpc -> + lwt_log_notice "The Tezos monitor RPC is now running!" >>= fun () -> + return (Queues.feeders node.queue_state, + (Lwt_exit.termination_thread >>= fun x -> + lwt_log_notice "Shutting down the RPC server..." >>= fun () -> + Lwt_utils.may ~f:RPC_server.shutdown rpc >>= fun () -> + lwt_log_notice "BYE (%d)" x)) + + let process cctxt workers delegates node_uri config = + let run = + Lwt.catch + (fun () -> run cctxt workers delegates node_uri config) + (function + |Unix.Unix_error(Unix.EADDRINUSE, "bind","") -> + begin + resolve_rpc_listening_addrs config.listen_host config.listen_port >>= fun addrlist -> + fail (RPC_Port_already_in_use addrlist) + end + | exn -> Lwt.return (error_exn exn) + ) in + run >>=? fun (report, launch) -> + return { report ; launch } + + (** A dummy process for when we don't actually want monitoring. Event reports are + * blackholed and launch hangs forever so it doesn't ever terminate the process + * when run in parallel with a daemon. + *) + let non_process = + return { + report = Queues.null_feeders ; + launch = fst (Lwt.task ()) ; + } + + let monitoring cctxt workers delegates node_uri = + function + | None -> non_process + | Some config -> process cctxt workers delegates node_uri config + +end + +module Baker_monitor_type = Event_server_type(Baker_queues) +module Baker_monitor = Event_server(Baker_queues) +module Endorser_monitor_type = Event_server_type(Endorser_queues) +module Endorser_monitor = Event_server(Endorser_queues) +module Accuser_monitor_type = Event_server_type(Accuser_queues) +module Accuser_monitor = Event_server(Accuser_queues) + +let default_baker_rpc_port = 7732 +let default_endorser_rpc_port = 7832 +let default_accuser_rpc_port = 7932 + +let build_rpc_config ~monitor ~monitor_host ~monitor_port ~monitor_cert ~monitor_key = + if monitor then + begin + match monitor_cert, monitor_key with + | None, None -> return None + | Some cert, Some key -> return @@ Some { cert ; key } + | _, _ -> fail (Bad_TLS_config ()) + end >>=? fun tls -> + return @@ Some { + listen_host = monitor_host ; + listen_port = monitor_port ; + tls ; + cors_origins = [] ; + cors_headers = [] ; + } + else + return None + +let rpc : int -> rpc Data_encoding.t = fun default_rpc_port -> + let open Data_encoding in + conv + (fun { cors_origins ; cors_headers ; listen_host ; listen_port ; tls } -> + let cert, key = + match tls with + | None -> None, None + | Some { cert ; key } -> Some cert, Some key in + (listen_host, listen_port, cors_origins, cors_headers, cert, key )) + (fun (listen_host, listen_port, cors_origins, cors_headers, cert, key ) -> + let tls = + match cert, key with + | None, _ | _, None -> None + | Some cert, Some key -> Some { cert ; key } in + { listen_host ; listen_port ; cors_origins ; cors_headers ; tls }) + (obj6 + (dft "listen-host" + ~description: "Host to listen to. If the host is not specified, \ + all interfaces will be assumed." + string "") + (dft "listen-port" + ~description: (Printf.sprintf + "Port to listen to. If the port is not specified, \ + the default port %d will be assumed." default_rpc_port) + string (string_of_int default_rpc_port)) + (dft "cors-origin" + ~description: "Cross Origin Resource Sharing parameters, see \ + https://en.wikipedia.org/wiki/Cross-origin_resource_sharing." + (list string) default_rpc.cors_origins) + (dft "cors-headers" + ~description: "Cross Origin Resource Sharing parameters, see \ + https://en.wikipedia.org/wiki/Cross-origin_resource_sharing." + (list string) default_rpc.cors_headers) + (opt "crt" + ~description: "Certificate file (necessary when TLS is used)." + string) + (opt "key" + ~description: "Key file (necessary when TLS is used)." + string)) diff --git a/src/proto_alpha/lib_delegate/client_baking_rpc.mli b/src/proto_alpha/lib_delegate/client_baking_rpc.mli new file mode 100644 index 0000000000000000000000000000000000000000..61ccb7487d693b773865d87117a74f0c19851134 --- /dev/null +++ b/src/proto_alpha/lib_delegate/client_baking_rpc.mli @@ -0,0 +1,116 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Tezos_baking_alpha_services.Event_queues + +type error += RPC_Port_already_in_use of P2p_point.Id.t list +type error += Bad_TLS_config of unit + +type rpc = { + listen_host : string ; + listen_port : string ; + cors_origins : string list ; + cors_headers : string list ; + tls : tls option ; +} + +and tls = { + cert : string ; + key : string ; +} + +val default_rpc : rpc + +module type QUEUES = sig + type feeders +end + +module Baker_queues: sig + type feeders = { + action : string -> Baked_event.t -> unit ; + revelation : string -> Revelation_event.t -> unit; + error : string -> Error_event.t -> unit ; + block : string -> Block_event.t -> unit ; + } +end + +module Endorser_queues: sig + type feeders = { + action : string -> Endorsement_event.t -> unit ; + error : string -> Error_event.t -> unit ; + block : string -> Block_event.t -> unit ; + } +end + +module Accuser_queues: sig + type feeders = { + action : string -> Accusation_event.t -> unit ; + error : string -> Error_event.t -> unit ; + block : string -> Block_event.t -> unit ; + } +end + +module Event_server_type(Queues: QUEUES): sig + module type T = sig + type t = { + report : Queues.feeders ; + launch : unit Lwt.t ; + } + + (** Run an RPC server to serve configuration data and + * event logs. In the event that the configuration + * is None, instead provide a mock of the RPC server's + * in-process interface that does nothing. + *) + val monitoring: + #Client_context.wallet -> + string list -> + Signature.public_key_hash list -> + Uri.t -> + rpc option -> + t tzresult Lwt.t + end +end + +module Baker_monitor_type: module type of Event_server_type(Baker_queues) +module Baker_monitor: Baker_monitor_type.T +module Endorser_monitor_type: module type of Event_server_type(Endorser_queues) +module Endorser_monitor: Endorser_monitor_type.T +module Accuser_monitor_type: module type of Event_server_type(Accuser_queues) +module Accuser_monitor: Accuser_monitor_type.T + +val build_rpc_config: + monitor:bool -> + monitor_host:string -> + monitor_port:string -> + monitor_cert:string option -> + monitor_key:string option -> + rpc option tzresult Lwt.t + +val default_baker_rpc_port : int +val default_endorser_rpc_port : int +val default_accuser_rpc_port : int + +val rpc : int -> rpc Data_encoding.t diff --git a/src/proto_alpha/lib_delegate/client_daemon.ml b/src/proto_alpha/lib_delegate/client_daemon.ml index 128b272f5cae88bf873e4f4321387b9a92538547..cee6fb6a382978006aa5c48e46175ab02d2d228b 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.ml +++ b/src/proto_alpha/lib_delegate/client_daemon.ml @@ -23,6 +23,8 @@ (* *) (*****************************************************************************) +include Tezos_stdlib.Logging.Make_semantic(struct let name = "client.daemon" end) + let await_bootstrapped_node (cctxt: #Proto_alpha.full) = (* Waiting for the node to be synchronized *) cctxt#message "Waiting for the node to be synchronized with the its \ @@ -31,46 +33,139 @@ let await_bootstrapped_node (cctxt: #Proto_alpha.full) = module Endorser = struct - let run (cctxt : #Proto_alpha.full) ~delay ?min_date delegates = - await_bootstrapped_node cctxt >>=? fun _ -> - Client_baking_blocks.monitor_heads - ~next_protocols:(Some [Proto_alpha.hash]) - cctxt `Main >>=? fun block_stream -> - Client_baking_endorsement.create cctxt ~delay delegates block_stream >>=? fun () -> - ignore min_date; - return_unit + let run (cctxt : #Proto_alpha.full) + ?rpc ~delay ?min_date:_ delegates = + Client_baking_rpc.Endorser_monitor.monitoring + cctxt ["endorser"] delegates cctxt#base rpc >>=? fun { launch; report } -> + ignore @@ Tezos_stdlib.Logging.(tap (fun msg -> + let event = Tag.find event msg.tags in + let trace : error list option = match (Tag.find exn msg.tags, Tag.find errs_tag msg.tags) with + | (None, None) -> None + | (Some exn, None) -> Some [Exn exn] + | (None, Some errs) -> Some errs + | (Some exn, Some errs) -> Some (Exn exn :: errs) + in + match event, trace with + | Some "injected_endorsement", _ -> + report.action "endorsement" { + hash = Tag.get Block_hash.Logging.tag msg.tags ; + level = Tag.get Logging.level_tag msg.tags ; + name = Tag.get Client_keys.Logging.tag msg.tags ; + delegate = Tag.get Signature.Public_key_hash.Logging.tag msg.tags ; + oph = Tag.get Operation_hash.Logging.tag msg.tags ; + } + | _, Some trace -> begin + match msg.level with + | Error | Fatal -> report.error "error" {message = msg.text ; trace = trace} + | _ -> () + end + | _, _ -> () + )) ; + Lwt.pick [ + launch >>= (fun () -> return_unit); + await_bootstrapped_node cctxt >>=? fun _ -> + Client_baking_blocks.monitor_heads + ~report:(report.block "blocks") + ~next_protocols:(Some [Proto_alpha.hash]) + cctxt `Main >>=? fun block_stream -> + Client_baking_endorsement.create cctxt ~delay delegates block_stream >>=? fun () -> + return_unit + ] end module Baker = struct - let run - (cctxt : #Proto_alpha.full) + let run (cctxt : #Proto_alpha.full) + ?rpc ?fee_threshold ?max_priority - ?min_date + ?min_date:_ ~context_path ~max_waiting_time delegates = - await_bootstrapped_node cctxt >>=? fun _ -> - Client_baking_blocks.monitor_heads - ~next_protocols:(Some [Proto_alpha.hash]) - cctxt `Main >>=? fun block_stream -> - Client_baking_forge.create cctxt - ?fee_threshold ?max_priority ~max_waiting_time ~context_path delegates block_stream >>=? fun () -> - ignore min_date; - return_unit + Client_baking_rpc.Baker_monitor.monitoring + cctxt ["baker"] delegates cctxt#base rpc >>=? fun { launch; report } -> + ignore @@ Tezos_stdlib.Logging.(tap (fun msg -> + let event = Tag.find event msg.tags in + let trace : error list option = match (Tag.find exn msg.tags, Tag.find errs_tag msg.tags) with + | (None, None) -> None + | (Some exn, None) -> Some [Exn exn] + | (None, Some errs) -> Some errs + | (Some exn, Some errs) -> Some (Exn exn :: errs) + in + match event, trace with + | Some "inject_baked_block", _ -> + report.action "baking" { + hash = Tag.get Block_hash.Logging.tag msg.tags ; + signed_header = Tag.get Logging.signed_header_tag msg.tags ; + operations = Tag.get Logging.operations_tag msg.tags ; + } + | Some "reveal_nonce", _ -> + report.revelation "baking" { + nonce = Tag.get Logging.nonce_tag msg.tags ; + level = Tag.get Logging.level_tag msg.tags ; + oph = Tag.get Operation_hash.Logging.tag msg.tags ; + } + | _, Some trace -> begin + match msg.level with + | Error | Fatal -> report.error "error" {message = msg.text ; trace = trace} + | _ -> () + end + | _, _ -> () + )) ; + Lwt.pick [ + launch >>= (fun () -> return_unit); + await_bootstrapped_node cctxt >>=? fun _ -> + Client_baking_blocks.monitor_heads + ~report:(report.block "blocks") + ~next_protocols:(Some [Proto_alpha.hash]) + cctxt `Main >>=? fun block_stream -> + Client_baking_forge.create cctxt + ?fee_threshold ?max_priority ~max_waiting_time ~context_path delegates block_stream >>=? fun () -> + return_unit + ] end module Accuser = struct - let run (cctxt : #Proto_alpha.full) ~preserved_levels = - await_bootstrapped_node cctxt >>=? fun _ -> - Client_baking_blocks.monitor_valid_blocks - ~next_protocols:(Some [Proto_alpha.hash]) - cctxt ~chains:[ `Main ] () >>=? fun valid_blocks_stream -> - Client_baking_denunciation.create cctxt ~preserved_levels valid_blocks_stream >>=? fun () -> - return_unit + let run (cctxt : #Proto_alpha.full) + ?rpc ~preserved_levels = + Client_baking_rpc.Accuser_monitor.monitoring + cctxt ["accuser"] [] cctxt#base rpc >>=? fun { launch; report } -> + ignore @@ Tezos_stdlib.Logging.(tap (fun msg -> + let event = Tag.find event msg.tags in + let trace : error list option = match (Tag.find exn msg.tags, Tag.find errs_tag msg.tags) with + | (None, None) -> None + | (Some exn, None) -> Some [Exn exn] + | (None, Some errs) -> Some errs + | (Some exn, Some errs) -> Some (Exn exn :: errs) + in + match event, trace with + | Some "double_baking_denounced", _ + | Some "double_endorsement_denounced", _ -> + report.action "denunciation" { + sin = if event = Some "double_baking_denounced" then "double_baking" else "double_endorsement" ; + oph = Tag.get Operation_hash.Logging.tag msg.tags ; + raw = Tag.get Logging.signed_operation_tag msg.tags ; + } + | _, Some trace -> begin + match msg.level with + | Error | Fatal -> report.error "error" {message = msg.text ; trace = trace} + | _ -> () + end + | _, _ -> () + )) ; + Lwt.pick [ + launch >>= (fun () -> return_unit); + await_bootstrapped_node cctxt >>=? fun _ -> + Client_baking_blocks.monitor_valid_blocks + ~report:(report.block "blocks") + ~next_protocols:(Some [Proto_alpha.hash]) + cctxt ~chains:[ `Main ] () >>=? fun valid_blocks_stream -> + Client_baking_denunciation.create cctxt ~preserved_levels valid_blocks_stream >>=? fun () -> + return_unit + ] end diff --git a/src/proto_alpha/lib_delegate/client_daemon.mli b/src/proto_alpha/lib_delegate/client_daemon.mli index d6e781ed74037d72b2903b5756148aa130e33a31..809fda96ccea009e9676f78d961d425cf6155c3c 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.mli +++ b/src/proto_alpha/lib_delegate/client_daemon.mli @@ -29,6 +29,7 @@ open Alpha_context module Endorser : sig val run: #Proto_alpha.full -> + ?rpc: Client_baking_rpc.rpc -> delay: int -> ?min_date: Time.t -> public_key_hash list -> unit tzresult Lwt.t @@ -37,6 +38,7 @@ end module Baker : sig val run: #Proto_alpha.full -> + ?rpc: Client_baking_rpc.rpc -> ?fee_threshold: Tez.tez -> ?max_priority: int -> ?min_date: Time.t -> @@ -48,6 +50,7 @@ end module Accuser : sig val run: #Proto_alpha.full -> + ?rpc: Client_baking_rpc.rpc -> preserved_levels: int -> unit tzresult Lwt.t end diff --git a/src/proto_alpha/lib_delegate/delegate_commands.ml b/src/proto_alpha/lib_delegate/delegate_commands.ml index 519663d6ceb39ad76b31742d9f9eb38040d6bb7b..7bac450ba76b4ad69224bf902cb34ceabf635e00 100644 --- a/src/proto_alpha/lib_delegate/delegate_commands.ml +++ b/src/proto_alpha/lib_delegate/delegate_commands.ml @@ -93,23 +93,29 @@ let baker_commands () = in [ command ~group ~desc: "Launch the baker daemon." - (args3 max_priority_arg fee_threshold_arg max_waiting_time_arg) + Daemon.(args8 max_priority_arg fee_threshold_arg max_waiting_time_arg monitor_switch + monitor_host (monitor_port Client_baking_rpc.default_baker_rpc_port) + monitor_cert monitor_key) (prefixes [ "run" ; "with" ; "local" ; "node" ] @@ param ~name:"context_path" ~desc:"Path to the node data directory (e.g. $HOME/.tezos-node)" directory_parameter @@ seq_of_param Client_keys.Public_key_hash.alias_param) - (fun (max_priority, fee_threshold, max_waiting_time) node_path delegates cctxt -> - Tezos_signer_backends.Encrypted.decrypt_list - cctxt (List.map fst delegates) >>=? fun () -> - Client_daemon.Baker.run cctxt - ?fee_threshold - ?max_priority - ~max_waiting_time - ~min_date:((Time.add (Time.now ()) (Int64.neg 1800L))) - ~context_path:(Filename.concat node_path "context") - (List.map snd delegates) + (fun (max_priority, fee_threshold, max_waiting_time, monitor, monitor_host, + monitor_port, monitor_cert, monitor_key) node_path delegates cctxt -> + Client_baking_rpc.build_rpc_config + ~monitor ~monitor_host ~monitor_port ~monitor_cert ~monitor_key >>=? fun rpc -> + Tezos_signer_backends.Encrypted.decrypt_list + cctxt (List.map fst delegates) >>=? fun () -> + Client_daemon.Baker.run cctxt + ?rpc + ?fee_threshold + ?max_priority + ~max_waiting_time + ~min_date:((Time.add (Time.now ()) (Int64.neg 1800L))) + ~context_path:(Filename.concat node_path "context") + (List.map snd delegates) ) ] @@ -121,16 +127,22 @@ let endorser_commands () = in [ command ~group ~desc: "Launch the endorser daemon" - (args1 endorsement_delay_arg) + Daemon.(args6 endorsement_delay_arg monitor_switch + monitor_host (monitor_port Client_baking_rpc.default_endorser_rpc_port) + monitor_cert monitor_key) (prefixes [ "run" ] @@ seq_of_param Client_keys.Public_key_hash.alias_param) - (fun endorsement_delay delegates cctxt -> - Tezos_signer_backends.Encrypted.decrypt_list - cctxt (List.map fst delegates) >>=? fun () -> - Client_daemon.Endorser.run cctxt - ~delay:endorsement_delay - ~min_date:((Time.add (Time.now ()) (Int64.neg 1800L))) - (List.map snd delegates) + (fun (endorsement_delay, monitor, monitor_host, monitor_port, + monitor_cert, monitor_key) delegates cctxt -> + Client_baking_rpc.build_rpc_config + ~monitor ~monitor_host ~monitor_port ~monitor_cert ~monitor_key >>=? fun rpc -> + Tezos_signer_backends.Encrypted.decrypt_list + cctxt (List.map fst delegates) >>=? fun () -> + Client_daemon.Endorser.run cctxt + ?rpc + ~delay:endorsement_delay + ~min_date:((Time.add (Time.now ()) (Int64.neg 1800L))) + (List.map snd delegates) ) ] @@ -142,9 +154,14 @@ let accuser_commands () = in [ command ~group ~desc: "Launch the accuser daemon" - (args1 preserved_levels_arg) + Daemon.(args6 preserved_levels_arg monitor_switch + monitor_host (monitor_port Client_baking_rpc.default_accuser_rpc_port) + monitor_cert monitor_key) (prefixes [ "run" ] @@ stop) - (fun preserved_levels cctxt -> - Client_daemon.Accuser.run ~preserved_levels cctxt) ; + (fun (preserved_levels, monitor, monitor_host, monitor_port, + monitor_cert, monitor_key) cctxt -> + Client_baking_rpc.build_rpc_config + ~monitor ~monitor_host ~monitor_port ~monitor_cert ~monitor_key >>=? fun rpc -> + Client_daemon.Accuser.run ?rpc ~preserved_levels cctxt) ; ] diff --git a/src/proto_alpha/lib_delegate/dune b/src/proto_alpha/lib_delegate/dune index ed916b4a9a3c40eae863c979cd01fcedaf951db0..ae0041789fc56e2e50ec7ec679df0a4f26c10729 100644 --- a/src/proto_alpha/lib_delegate/dune +++ b/src/proto_alpha/lib_delegate/dune @@ -5,11 +5,13 @@ tezos-protocol-alpha tezos-protocol-environment tezos-shell-services + tezos-baking-alpha-services tezos-client-base tezos-client-alpha tezos-client-commands tezos-storage - tezos-rpc) + tezos-rpc-http + tezos-stdlib-unix) (library_flags (:standard -linkall)) (modules (:standard \ delegate_commands @@ -22,7 +24,8 @@ -open Tezos_client_alpha -open Tezos_client_commands -open Tezos_storage - -open Tezos_rpc))) + -open Tezos_rpc_http + -open Tezos_stdlib_unix))) (library (name tezos_baking_alpha_commands) diff --git a/src/proto_alpha/lib_delegate/logging.ml b/src/proto_alpha/lib_delegate/logging.ml index 191f0fff2608ce28a485627a07bc275449d84479..3b8247f775c34b3315cd6aab688f06e6db6c624d 100644 --- a/src/proto_alpha/lib_delegate/logging.ml +++ b/src/proto_alpha/lib_delegate/logging.ml @@ -35,6 +35,8 @@ let current_slots_tag = Tag.def ~doc:"Number of baking slots that can be baked a let future_slots_tag = Tag.def ~doc:"Number of baking slots in the foreseeable future but not yet bakeable" "future_slots" Format.pp_print_int let timespan_tag = Tag.def ~doc:"Time in seconds" "timespan" (fun fmt i -> Format.fprintf fmt "%Lds" i) +let signed_header_tag = Tag.def ~doc:"Signed header" "signed_header" MBytes.pp_hex +let signed_operation_tag = Tag.def ~doc:"Signed operation" "signed_operation" MBytes.pp_hex let operations_tag = Tag.def ~doc:"Block Operations" "operations" (Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf "+") @@ -48,8 +50,13 @@ let denounced_endorsements_slots_tag = Tag.def ~doc:"Endorsement Slots" "denounc let denouncement_source_tag = Tag.def ~doc:"Denounce Source" "source" Format.pp_print_text let level_tag = Tag.def ~doc:"Level" "level" Raw_level.pp +let nonce_tag = Tag.def ~doc:"Nonce" "nonce" Data_encoding.Json.(fun ppf nonce -> pp ppf (construct Nonce.encoding nonce)) +let chain_tag = Tag.def ~doc:"Chain selector" "chain" Format.(fun ppf chain -> pp_print_string ppf @@ Block_services.chain_to_string chain) +let block_tag = Tag.def ~doc:"Block selector" "block" Format.(fun ppf block -> pp_print_string ppf @@ Block_services.to_string block) let worker_tag = Tag.def ~doc:"Worker in which event occurred" "worker" Format.pp_print_text +let operation_tag = Tag.def ~doc:"Operation" "operation" Tezos_base.Operation.pp + let conflicting_endorsements_tag = Tag.def ~doc:"Two conflicting endorsements signed by the same key" "conflicting_endorsements" Format.( fun ppf (a,b) -> fprintf ppf "%a / %a" Operation_hash.pp (Operation.hash a) Operation_hash.pp (Operation.hash b)) diff --git a/src/proto_alpha/lib_delegate/logging.mli b/src/proto_alpha/lib_delegate/logging.mli index 868594ee9c551071cb4013c4ebdffcb742bc9ee2..b653daf02195751b01372d4fc56923dc1ac00665 100644 --- a/src/proto_alpha/lib_delegate/logging.mli +++ b/src/proto_alpha/lib_delegate/logging.mli @@ -32,14 +32,20 @@ val current_slots_tag : int Tag.def val future_slots_tag : int Tag.def val timespan_tag : int64 Tag.def -val operations_tag : Proto_alpha.Alpha_context.Operation.raw list list Tag.def +val signed_header_tag : MBytes.t Tag.def +val signed_operation_tag : MBytes.t Tag.def +val operations_tag : Tezos_base.Operation.t list list Tag.def val bake_op_count_tag : int Tag.def val endorsement_slot_tag : int Tag.def val endorsement_slots_tag : int list Tag.def val denounced_endorsements_slots_tag : int list Tag.def val denouncement_source_tag : string Tag.def val level_tag : Proto_alpha.Alpha_context.Raw_level.t Tag.def +val nonce_tag : Proto_alpha.Alpha_context.Nonce.t Tag.def +val chain_tag : Block_services.chain Tag.def +val block_tag : Block_services.block Tag.def val worker_tag : string Tag.def +val operation_tag : Tezos_base.Operation.t Tag.def open Proto_alpha.Alpha_context val conflicting_endorsements_tag : (Kind.endorsement operation * Kind.endorsement operation) Tag.def diff --git a/src/proto_alpha/lib_delegate/tezos-baking-alpha.opam b/src/proto_alpha/lib_delegate/tezos-baking-alpha.opam index 87e71ee1c03735bffe8376855ae7ba9418cbac88..fbcdb76282e87b992a992b88564d3d591945f1c2 100644 --- a/src/proto_alpha/lib_delegate/tezos-baking-alpha.opam +++ b/src/proto_alpha/lib_delegate/tezos-baking-alpha.opam @@ -13,9 +13,12 @@ depends: [ "tezos-protocol-environment" "tezos-protocol-alpha" "tezos-shell-services" + "tezos-baking-alpha-services" "tezos-client-base" "tezos-client-commands" "tezos-client-alpha" + "tezos-rpc-http" + "tezos-stdlib-unix" "tezos-node" { test } "tezos-client-genesis" { test } "tezos-client-base-unix" { test } diff --git a/src/proto_alpha/lib_delegate_services/accuser_services.ml b/src/proto_alpha/lib_delegate_services/accuser_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..d3d6df66a257519b4c7dfda756e11841a4eb468e --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/accuser_services.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Daemon_services.Make(Event_queues.Accuser_queues) diff --git a/src/proto_alpha/lib_delegate_services/accuser_services.mli b/src/proto_alpha/lib_delegate_services/accuser_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..718c608270503995746307d75b96691762db9cb8 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/accuser_services.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open RPC_context + +val events: + #simple -> (Time.t * Event_queues.Accuser_queues.output) tzresult Lwt.t +val config: + #simple -> Config_catalog.t tzresult Lwt.t + +module S : sig + + val events : + ([ `GET ], unit, + unit, unit, unit, + (Time.t * Event_queues.Accuser_queues.output)) RPC_service.t + + val config : + ([ `GET ], unit, + unit, unit, unit, + Config_catalog.t) RPC_service.t + +end diff --git a/src/proto_alpha/lib_delegate_services/baker_services.ml b/src/proto_alpha/lib_delegate_services/baker_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..9b061b12d7958c13c118f275a36268ac063073fa --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/baker_services.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Daemon_services.Make(Event_queues.Baker_queues) diff --git a/src/proto_alpha/lib_delegate_services/baker_services.mli b/src/proto_alpha/lib_delegate_services/baker_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..7bddc5c4bb52350b8080c955063b036adaae230c --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/baker_services.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open RPC_context + +val events: + #simple -> (Time.t * Event_queues.Baker_queues.output) tzresult Lwt.t +val config: + #simple -> Config_catalog.t tzresult Lwt.t + +module S : sig + + val events : + ([ `GET ], unit, + unit, unit, unit, + (Time.t * Event_queues.Baker_queues.output)) RPC_service.t + + val config : + ([ `GET ], unit, + unit, unit, unit, + Config_catalog.t) RPC_service.t + +end diff --git a/src/proto_alpha/lib_delegate_services/config_catalog.ml b/src/proto_alpha/lib_delegate_services/config_catalog.ml new file mode 100644 index 0000000000000000000000000000000000000000..6e61ebab359c7b8fa7926870b8aad33b05d36db7 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/config_catalog.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Data_encoding + +let uri_encoding = + conv + Uri.to_string + Uri.of_string + string + +type t = { + start_time : Time.t ; + delegates : Signature.Public_key_hash.t list ; + workers : string list ; + node_uri : Uri.t ; +} + +let encoding = + conv + (fun { start_time ; delegates ; workers ; node_uri } -> + ( start_time , delegates , workers , node_uri )) + (fun ( start_time , delegates , workers , node_uri ) -> + { start_time ; delegates ; workers ; node_uri }) + (obj4 + (req "start_time" Time.encoding) + (req "delegates" (list Signature.Public_key_hash.encoding)) + (req "workers" (list string)) + (req "node_uri" uri_encoding)) diff --git a/src/proto_alpha/lib_delegate_services/config_catalog.mli b/src/proto_alpha/lib_delegate_services/config_catalog.mli new file mode 100644 index 0000000000000000000000000000000000000000..ea9fdf88e645383bfb3461a1ad3e3632d698b864 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/config_catalog.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +type t = { + start_time : Time.t ; + delegates : Signature.Public_key_hash.t list ; + workers : string list ; + node_uri : Uri.t ; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_delegate_services/daemon_services.ml b/src/proto_alpha/lib_delegate_services/daemon_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..bfcff96b895a294142299dce68343e18f8f52bef --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/daemon_services.ml @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +module Make(Queues: Event_queues.Queues_svc.T) = struct + + module S = struct + let events = + RPC_service.get_service + ~description:"Read the events from the daemon's ring buffers." + ~query:RPC_query.empty + ~output:Data_encoding.(merge_objs (obj1 (req "start_time" Time.encoding)) Queues.output_encoding) + RPC_path.(root / "events") + + let config = + RPC_service.get_service + ~description:"Read the configuration of the running node." + ~query:RPC_query.empty + ~output:Config_catalog.encoding + RPC_path.(root / "config") + end + + open RPC_context + + let events ctxt = make_call S.events ctxt () () () + let config ctxt = make_call S.config ctxt () () () + +end diff --git a/src/proto_alpha/lib_delegate_services/daemon_services.mli b/src/proto_alpha/lib_delegate_services/daemon_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..e9dbb1f3d42c84e88b2abf31538bd04a6a5effef --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/daemon_services.mli @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open RPC_context + +module Make(Queues: Event_queues.Queues_svc.T): sig + + val events: + #simple -> (Time.t * Queues.output) tzresult Lwt.t + val config: + #simple -> Config_catalog.t tzresult Lwt.t + + module S : sig + + val events : + ([ `GET ], unit, + unit, unit, unit, + (Time.t * Queues.output)) RPC_service.t + + val config : + ([ `GET ], unit, + unit, unit, unit, + Config_catalog.t) RPC_service.t + + end + +end diff --git a/src/proto_alpha/lib_delegate_services/dune b/src/proto_alpha/lib_delegate_services/dune new file mode 100644 index 0000000000000000000000000000000000000000..ba7e68257a045d11606701197d7c071c62d9afbd --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/dune @@ -0,0 +1,18 @@ +(library + (name tezos_baking_alpha_services) + (public_name tezos-baking-alpha-services) + (libraries tezos-base + tezos-protocol-environment + tezos-protocol-alpha + tezos-client-base + tezos-client-alpha) + (flags (:standard -w +27@8 + -safe-string + -open Tezos_base__TzPervasives + -open Tezos_client_base + -open Tezos_client_alpha))) + +(alias + (name runtest_indent) + (deps (glob_files *.ml{,i})) + (action (run bash %{libexec:tezos-stdlib:test-ocp-indent.sh} %{deps}))) diff --git a/src/proto_alpha/lib_delegate_services/endorser_services.ml b/src/proto_alpha/lib_delegate_services/endorser_services.ml new file mode 100644 index 0000000000000000000000000000000000000000..ffff872acdacf44e7743fcfb215ab21d9403d361 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/endorser_services.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Daemon_services.Make(Event_queues.Endorser_queues) diff --git a/src/proto_alpha/lib_delegate_services/endorser_services.mli b/src/proto_alpha/lib_delegate_services/endorser_services.mli new file mode 100644 index 0000000000000000000000000000000000000000..6c235903ed1e231ba80a72907464ed1645ca4344 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/endorser_services.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open RPC_context + +val events: + #simple -> (Time.t * Event_queues.Endorser_queues.output) tzresult Lwt.t +val config: + #simple -> Config_catalog.t tzresult Lwt.t + +module S : sig + + val events : + ([ `GET ], unit, + unit, unit, unit, + (Time.t * Event_queues.Endorser_queues.output)) RPC_service.t + + val config : + ([ `GET ], unit, + unit, unit, unit, + Config_catalog.t) RPC_service.t + +end diff --git a/src/proto_alpha/lib_delegate_services/event_queues.ml b/src/proto_alpha/lib_delegate_services/event_queues.ml new file mode 100644 index 0000000000000000000000000000000000000000..742c54b8dea7cd5478390dbc1669fb31ed81b5d6 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/event_queues.ml @@ -0,0 +1,189 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Proto_alpha + +module type EVENT = sig + type t + val name: string + val capacity: int + val encoding: t Data_encoding.t +end + +module Queues_svc = struct + + module type T = sig + type output + val output_encoding: output Data_encoding.t + end + + module Nil = struct + type output = unit + let output_encoding = Data_encoding.empty + end + + module Cons (E: EVENT)(QS: T) = struct + type event = int * Time.t * string * E.t + + type output = event list * QS.output + + let event_encoding = let open Data_encoding in + obj4 + (req "seq" int31) + (req "time" Time.encoding) + (req "worker" string) + (req "detail" E.encoding) + + let output_encoding = let open Data_encoding in + merge_objs (obj1 (req E.name (list event_encoding))) QS.output_encoding + end + +end + +module Error_event = struct + let name = "errors" + let capacity = 20 + type t = { + message: string option ; + trace: error list ; + } + let encoding = let open Data_encoding in + conv + (fun { message ; trace } -> + ( message , trace )) + (fun ( message , trace ) -> + { message ; trace }) + (obj2 + (opt "message" string) + (req "trace" (list error_encoding))) +end + +module Baked_event = struct + let name = "baked" + let capacity = 20 + type t = { + hash: Block_hash.t ; + signed_header: MBytes.t ; + operations: Tezos_base.Operation.t list list; + } + let encoding = let open Data_encoding in + conv + (fun { hash ; signed_header ; operations } -> + ( hash , signed_header , operations )) + (fun ( hash , signed_header , operations ) -> + { hash ; signed_header ; operations }) + (obj3 + (req "hash" Block_hash.encoding) + (req "signed_header" bytes) + (req "operations" (list (list (dynamic_size Tezos_base.Operation.encoding))))) +end + +module Revelation_event = struct + let name = "revealed" + let capacity = 20 + type t = { + nonce: Alpha_context.Nonce.t ; + level: Alpha_context.Raw_level.t ; + oph: Operation_hash.t ; + } + let encoding = let open Data_encoding in + conv + (fun { nonce ; level ; oph } -> + ( nonce , level , oph )) + (fun ( nonce , level , oph ) -> + { nonce ; level ; oph }) + (obj3 + (req "nonce" Alpha_context.Nonce.encoding) + (req "level" Alpha_context.Raw_level.encoding) + (req "oph" Operation_hash.encoding)) +end + +module Endorsement_event = struct + let name = "endorsed" + let capacity = 20 + type t = { + hash: Block_hash.t ; + level: Alpha_context.Raw_level.t ; + delegate: Signature.Public_key_hash.t ; + name: string ; + oph: Operation_hash.t ; + } + let encoding = let open Data_encoding in + conv + (fun { hash ; level ; delegate ; name ; oph } -> + ( hash , level , delegate , name , oph )) + (fun ( hash , level , delegate , name , oph ) -> + { hash ; level ; delegate ; name ; oph }) + (obj5 + (req "hash" Block_hash.encoding) + (req "level" Alpha_context.Raw_level.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "name" string) + (req "oph" Operation_hash.encoding)) +end + +module Accusation_event = struct + let name = "accused" + let capacity = 20 + type t = { + sin : string ; + oph : Operation_hash.t ; + raw : MBytes.t ; + } + let encoding = let open Data_encoding in + conv + (fun { sin ; oph ; raw } -> ( sin , oph , raw )) + (fun ( sin , oph , raw ) -> { sin ; oph ; raw }) + (obj3 + (req "sin" string) + (req "oph" Operation_hash.encoding) + (req "raw" bytes)) +end + +module Block_event = struct + type t = Block_hash.t * Block_header.t + let encoding = let open Data_encoding in + dynamic_size + (merge_objs + (obj1 + (req "hash" Block_hash.encoding)) + Block_header.encoding) + let capacity = 20 + let name = "seen" +end + +open Queues_svc + +module Common_queues = + Cons(Error_event)( + Cons(Block_event)( + Nil)) + +module Baker_queues = + Queues_svc.Cons(Baked_event)( + Queues_svc.Cons(Revelation_event)( + Common_queues)) +module Endorser_queues = Queues_svc.Cons(Endorsement_event)(Common_queues) +module Accuser_queues = Queues_svc.Cons(Accusation_event)(Common_queues) diff --git a/src/proto_alpha/lib_delegate_services/event_queues.mli b/src/proto_alpha/lib_delegate_services/event_queues.mli new file mode 100644 index 0000000000000000000000000000000000000000..4a832d42db2974547f8f824f4af6c0c03317ac27 --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/event_queues.mli @@ -0,0 +1,122 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Proto_alpha + +(** Parameters defining an inspectable, named ring buffer of events. *) +module type EVENT = sig + type t + val name: string + val capacity: int + val encoding: t Data_encoding.t +end + +(** A monitoring service is defined in terms of a 'list' of ring buffers of events. *) +module Queues_svc : sig + + module type T = sig + type output + val output_encoding: output Data_encoding.t + end + + module Nil : T with type output = unit + + module Cons (E: EVENT)(QS: T) : T with type output = (int * Time.t * string * E.t) list * QS.output + +end + +module Error_event : sig + type t = { + message: string option ; + trace: error list ; + } + include EVENT with type t := t +end + +module Baked_event : sig + type t = { + hash: Block_hash.t ; + signed_header: MBytes.t ; + operations: Tezos_base.Operation.t list list; + } + include EVENT with type t := t +end + +module Revelation_event : sig + type t = { + nonce: Alpha_context.Nonce.t ; + level: Alpha_context.Raw_level.t ; + oph : Operation_hash.t ; + } + include EVENT with type t := t +end + +module Endorsement_event : sig + type t = { + hash: Block_hash.t ; + level: Alpha_context.Raw_level.t ; + delegate: Signature.Public_key_hash.t ; + name: string ; + oph: Operation_hash.t ; + } + include EVENT with type t := t +end + +module Accusation_event : sig + type t = { + sin: string ; + oph: Operation_hash.t ; + raw: MBytes.t ; + } + include EVENT with type t := t +end + +module Block_event : EVENT with type t = Block_hash.t * Block_header.t + +open Queues_svc + +(** All our daemons may experience errors, and all monitor the stream of + * blocks. Both errors and falling behind the chain head are things we + * may want to detect when monitoring. So we factor them out here. +*) +module Common_queues : Queues_svc.T with + type output = + Cons(Error_event)( + Cons(Block_event)( + Nil)).output + +module Baker_queues : Queues_svc.T with + type output = + Cons(Baked_event)( + Cons(Revelation_event)( + Common_queues)).output + +module Endorser_queues : Queues_svc.T with + type output = + Cons(Endorsement_event)(Common_queues).output + +module Accuser_queues : Queues_svc.T with + type output = + Cons(Accusation_event)(Common_queues).output diff --git a/src/proto_alpha/lib_delegate_services/tezos-baking-alpha-services.opam b/src/proto_alpha/lib_delegate_services/tezos-baking-alpha-services.opam new file mode 100644 index 0000000000000000000000000000000000000000..5c14f97d384440073fbff0215483ba530415acbc --- /dev/null +++ b/src/proto_alpha/lib_delegate_services/tezos-baking-alpha-services.opam @@ -0,0 +1,23 @@ +opam-version: "1.2" +version: "dev" +maintainer: "contact@tezos.com" +authors: [ "Tezos devteam" ] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "ocamlfind" { build } + "dune" { build & = "1.0.1" } + "tezos-base" + "tezos-protocol-environment" + "tezos-protocol-alpha" + "tezos-client-base" + "tezos-client-alpha" +] +build: [ + [ "dune" "build" "-p" name "-j" jobs ] +] +build-test: [ + [ "dune" "runtest" "-p" name "-j" jobs ] +]