2016-09-08 21:13:10 +04:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Copyright (c) 2014 - 2016. *)
|
|
|
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
|
|
(* *)
|
|
|
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
|
|
|
|
|
|
|
(* Tezos Command line interface - RPC Calls *)
|
|
|
|
|
|
|
|
open Lwt
|
|
|
|
open Cli_entries
|
2016-12-03 16:05:02 +04:00
|
|
|
open Client_commands
|
2016-09-08 21:13:10 +04:00
|
|
|
open Logging.RPC
|
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let log_request { log } cpt url req =
|
|
|
|
log "requests" ">>>>%d: %s\n%s\n" cpt url req
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let log_response { log } cpt code ans =
|
|
|
|
log "requests" "<<<<%d: %s\n%s\n" cpt (Cohttp.Code.string_of_status code) ans
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
let cpt = ref 0
|
2016-12-11 19:34:58 +04:00
|
|
|
let make_request cctxt meth service json =
|
2016-09-08 21:13:10 +04:00
|
|
|
incr cpt ;
|
|
|
|
let cpt = !cpt in
|
2017-03-15 04:17:20 +04:00
|
|
|
let scheme = if cctxt.config.tls then "https" else "http" in
|
|
|
|
let host = cctxt.config.incoming_addr in
|
|
|
|
let port = cctxt.config.incoming_port in
|
2016-12-02 01:42:28 +04:00
|
|
|
let path = String.concat "/" service in
|
|
|
|
let uri = Uri.make ~scheme ~host ~port ~path () in
|
|
|
|
let string_uri = Uri.to_string uri in
|
2016-12-01 21:27:53 +04:00
|
|
|
let reqbody = Data_encoding_ezjsonm.to_string json in
|
2016-09-08 21:13:10 +04:00
|
|
|
let tzero = Unix.gettimeofday () in
|
|
|
|
catch
|
|
|
|
(fun () ->
|
|
|
|
let body = Cohttp_lwt_body.of_string reqbody in
|
2016-12-11 19:34:58 +04:00
|
|
|
Cohttp_lwt_unix.Client.call meth ~body uri >>= fun (code, ansbody) ->
|
2016-12-03 16:05:02 +04:00
|
|
|
log_request cctxt cpt string_uri reqbody >>= fun () ->
|
2016-09-08 21:13:10 +04:00
|
|
|
return (cpt, Unix.gettimeofday () -. tzero,
|
|
|
|
code.Cohttp.Response.status, ansbody))
|
|
|
|
(fun e ->
|
|
|
|
let msg = match e with
|
|
|
|
| Unix.Unix_error (e, _, _) -> Unix.error_message e
|
|
|
|
| e -> Printexc.to_string e in
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.error "cannot connect to the RPC server (%s)" msg)
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-11 19:34:58 +04:00
|
|
|
let get_streamed_json cctxt meth service json =
|
|
|
|
make_request cctxt meth service json >>= fun (_cpt, time, code, ansbody) ->
|
2016-09-08 21:13:10 +04:00
|
|
|
let ansbody = Cohttp_lwt_body.to_stream ansbody in
|
|
|
|
match code, ansbody with
|
|
|
|
| #Cohttp.Code.success_status, ansbody ->
|
2017-03-15 04:17:20 +04:00
|
|
|
(if cctxt.config.print_timings then
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s succeeded in %gs"
|
|
|
|
(String.concat "/" service) time
|
2016-11-22 17:23:40 +04:00
|
|
|
else Lwt.return ()) >>= fun () ->
|
2016-09-08 21:13:10 +04:00
|
|
|
Lwt.return (
|
|
|
|
Lwt_stream.filter_map_s
|
|
|
|
(function
|
|
|
|
| Ok v -> Lwt.return (Some v)
|
|
|
|
| Error msg ->
|
|
|
|
lwt_log_error
|
|
|
|
"Failed to parse json: %s" msg >>= fun () ->
|
|
|
|
Lwt.return None)
|
2016-12-01 21:27:53 +04:00
|
|
|
(Data_encoding_ezjsonm.from_stream ansbody))
|
2016-09-08 21:13:10 +04:00
|
|
|
| err, _ansbody ->
|
2017-03-15 04:17:20 +04:00
|
|
|
(if cctxt.config.print_timings then
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s failed in %gs"
|
|
|
|
(String.concat "/" service) time
|
2016-11-22 17:23:40 +04:00
|
|
|
else Lwt.return ()) >>= fun () ->
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s failed, server returned %s"
|
2016-11-22 17:23:40 +04:00
|
|
|
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.error "the RPC server returned a non-success status (%s)"
|
2016-09-08 21:13:10 +04:00
|
|
|
(Cohttp.Code.string_of_status err)
|
|
|
|
|
2016-12-11 19:34:58 +04:00
|
|
|
let get_json cctxt meth service json =
|
|
|
|
make_request cctxt meth service json >>= fun (cpt, time, code, ansbody) ->
|
2016-09-08 21:13:10 +04:00
|
|
|
Cohttp_lwt_body.to_string ansbody >>= fun ansbody ->
|
|
|
|
match code, ansbody with
|
|
|
|
| #Cohttp.Code.success_status, ansbody -> begin
|
2017-03-15 04:17:20 +04:00
|
|
|
(if cctxt.config.print_timings then
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s succeeded in %gs"
|
2016-11-22 17:23:40 +04:00
|
|
|
(String.concat "/" service) time
|
|
|
|
else Lwt.return ()) >>= fun () ->
|
2016-12-03 16:05:02 +04:00
|
|
|
log_response cctxt cpt code ansbody >>= fun () ->
|
2016-09-08 21:13:10 +04:00
|
|
|
if ansbody = "" then Lwt.return `Null
|
2016-12-01 21:27:53 +04:00
|
|
|
else match Data_encoding_ezjsonm.from_string ansbody with
|
2016-12-03 16:05:02 +04:00
|
|
|
| Error _ -> cctxt.error "the RPC server returned malformed JSON"
|
2016-09-08 21:13:10 +04:00
|
|
|
| Ok res -> Lwt.return res
|
|
|
|
end
|
|
|
|
| err, _ansbody ->
|
2017-03-15 04:17:20 +04:00
|
|
|
(if cctxt.config.print_timings then
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s failed in %gs"
|
2016-11-22 17:23:40 +04:00
|
|
|
(String.concat "/" service) time
|
|
|
|
else Lwt.return ()) >>= fun () ->
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.message "Request to /%s failed, server returned %s"
|
2016-11-22 17:23:40 +04:00
|
|
|
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.error "the RPC server returned a non-success status (%s)"
|
2016-09-08 21:13:10 +04:00
|
|
|
(Cohttp.Code.string_of_status err)
|
|
|
|
|
|
|
|
exception Unknown_error of Data_encoding.json
|
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let parse_answer cctxt service path json =
|
2016-09-08 21:13:10 +04:00
|
|
|
match RPC.read_answer service json with
|
|
|
|
| Error msg -> (* TODO print_error *)
|
2016-12-03 16:05:02 +04:00
|
|
|
cctxt.error "request to /%s returned wrong JSON (%s)\n%s"
|
2016-12-01 21:27:53 +04:00
|
|
|
(String.concat "/" path) msg (Data_encoding_ezjsonm.to_string json)
|
2016-09-08 21:13:10 +04:00
|
|
|
| Ok v -> return v
|
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let call_service0 cctxt service arg =
|
2016-12-11 19:34:58 +04:00
|
|
|
let meth, path, arg = RPC.forge_request service () arg in
|
|
|
|
get_json cctxt meth path arg >>= fun json ->
|
2016-12-03 16:05:02 +04:00
|
|
|
parse_answer cctxt service path json
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let call_service1 cctxt service a1 arg =
|
2016-12-11 19:34:58 +04:00
|
|
|
let meth, path, arg = RPC.forge_request service ((), a1) arg in
|
|
|
|
get_json cctxt meth path arg >>= fun json ->
|
2016-12-03 16:05:02 +04:00
|
|
|
parse_answer cctxt service path json
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let call_service2 cctxt service a1 a2 arg =
|
2016-12-11 19:34:58 +04:00
|
|
|
let meth, path, arg = RPC.forge_request service (((), a1), a2) arg in
|
|
|
|
get_json cctxt meth path arg >>= fun json ->
|
2016-12-03 16:05:02 +04:00
|
|
|
parse_answer cctxt service path json
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-03 16:05:02 +04:00
|
|
|
let call_streamed_service0 cctxt service arg =
|
2016-12-11 19:34:58 +04:00
|
|
|
let meth, path, arg = RPC.forge_request service () arg in
|
|
|
|
get_streamed_json cctxt meth path arg >|= fun st ->
|
2016-12-03 16:05:02 +04:00
|
|
|
Lwt_stream.map_s (parse_answer cctxt service path) st
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
module Services = Node_rpc_services
|
2016-12-03 16:05:02 +04:00
|
|
|
let errors cctxt =
|
|
|
|
call_service0 cctxt Services.Error.service ()
|
|
|
|
let forge_block cctxt ?net ?predecessor ?timestamp fitness ops header =
|
|
|
|
call_service0 cctxt Services.forge_block
|
2016-09-08 21:13:10 +04:00
|
|
|
(net, predecessor, timestamp, fitness, ops, header)
|
2016-12-03 16:05:02 +04:00
|
|
|
let validate_block cctxt net block =
|
|
|
|
call_service0 cctxt Services.validate_block (net, block)
|
2017-03-30 15:16:21 +04:00
|
|
|
let inject_block cctxt ?(async = false) ?(force = false) raw operations =
|
|
|
|
call_service0 cctxt Services.inject_block
|
|
|
|
{ raw ; blocking = not async ; force ; operations }
|
2017-03-30 15:08:33 +04:00
|
|
|
let inject_operation cctxt ?(async = false) ?force operation =
|
|
|
|
call_service0 cctxt Services.inject_operation (operation, not async, force)
|
|
|
|
let inject_protocol cctxt ?(async = false) ?force protocol =
|
|
|
|
call_service0 cctxt Services.inject_protocol (protocol, not async, force)
|
2017-02-28 03:48:22 +04:00
|
|
|
let bootstrapped cctxt =
|
|
|
|
call_streamed_service0 cctxt Services.bootstrapped ()
|
2016-12-03 16:05:02 +04:00
|
|
|
let complete cctxt ?block prefix =
|
2016-11-15 17:44:16 +04:00
|
|
|
match block with
|
|
|
|
| None ->
|
2016-12-03 16:05:02 +04:00
|
|
|
call_service1 cctxt Services.complete prefix ()
|
2016-11-15 17:44:16 +04:00
|
|
|
| Some block ->
|
2016-12-03 16:05:02 +04:00
|
|
|
call_service2 cctxt Services.Blocks.complete block prefix ()
|
|
|
|
let describe cctxt ?recurse path =
|
2016-12-11 19:34:58 +04:00
|
|
|
let meth, prefix, arg = RPC.forge_request Services.describe () recurse in
|
|
|
|
get_json cctxt meth (prefix @ path) arg >>=
|
2016-12-03 16:05:02 +04:00
|
|
|
parse_answer cctxt Services.describe prefix
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
module Blocks = struct
|
|
|
|
type block = Services.Blocks.block
|
|
|
|
|
|
|
|
type block_info = Services.Blocks.block_info = {
|
|
|
|
hash: Block_hash.t ;
|
|
|
|
predecessor: Block_hash.t ;
|
|
|
|
fitness: MBytes.t list ;
|
|
|
|
timestamp: Time.t ;
|
|
|
|
protocol: Protocol_hash.t option ;
|
2017-03-30 15:16:21 +04:00
|
|
|
operations_hash: Operation_list_list_hash.t ;
|
|
|
|
operations: Operation_hash.t list list option ;
|
2017-03-22 20:21:52 +04:00
|
|
|
data: MBytes.t option ;
|
2017-02-24 20:17:53 +04:00
|
|
|
net: Updater.Net_id.t ;
|
2016-09-08 21:13:10 +04:00
|
|
|
test_protocol: Protocol_hash.t option ;
|
2017-02-24 20:17:53 +04:00
|
|
|
test_network: (Updater.Net_id.t * Time.t) option ;
|
2016-09-08 21:13:10 +04:00
|
|
|
}
|
|
|
|
type preapply_param = Services.Blocks.preapply_param = {
|
|
|
|
operations: Operation_hash.t list ;
|
|
|
|
sort: bool ;
|
|
|
|
timestamp: Time.t option ;
|
|
|
|
}
|
|
|
|
type preapply_result = Services.Blocks.preapply_result = {
|
|
|
|
operations: error Updater.preapply_result ;
|
|
|
|
fitness: MBytes.t list ;
|
|
|
|
timestamp: Time.t ;
|
|
|
|
}
|
2016-12-03 16:05:02 +04:00
|
|
|
let net cctxt h = call_service1 cctxt Services.Blocks.net h ()
|
|
|
|
let predecessor cctxt h = call_service1 cctxt Services.Blocks.predecessor h ()
|
2017-02-15 23:38:00 +04:00
|
|
|
let predecessors cctxt h l = call_service1 cctxt Services.Blocks.predecessors h l
|
2016-12-03 16:05:02 +04:00
|
|
|
let hash cctxt h = call_service1 cctxt Services.Blocks.hash h ()
|
|
|
|
let timestamp cctxt h = call_service1 cctxt Services.Blocks.timestamp h ()
|
|
|
|
let fitness cctxt h = call_service1 cctxt Services.Blocks.fitness h ()
|
|
|
|
let operations cctxt h = call_service1 cctxt Services.Blocks.operations h ()
|
|
|
|
let protocol cctxt h = call_service1 cctxt Services.Blocks.protocol h ()
|
|
|
|
let test_protocol cctxt h = call_service1 cctxt Services.Blocks.test_protocol h ()
|
|
|
|
let test_network cctxt h = call_service1 cctxt Services.Blocks.test_network h ()
|
|
|
|
let preapply cctxt h ?timestamp ?(sort = false) operations =
|
|
|
|
call_service1 cctxt Services.Blocks.preapply h { operations ; sort ; timestamp }
|
|
|
|
let pending_operations cctxt block =
|
|
|
|
call_service1 cctxt Services.Blocks.pending_operations block ()
|
2017-03-22 20:21:52 +04:00
|
|
|
let info cctxt ?(operations = true) ?(data = true) h =
|
|
|
|
call_service1 cctxt Services.Blocks.info h (operations, data)
|
2016-12-03 16:05:02 +04:00
|
|
|
let complete cctxt block prefix =
|
|
|
|
call_service2 cctxt Services.Blocks.complete block prefix ()
|
2017-03-22 20:21:52 +04:00
|
|
|
let list cctxt ?(operations = false) ?(data = false)
|
|
|
|
?length ?heads ?delay ?min_date ?min_heads () =
|
2016-12-03 16:05:02 +04:00
|
|
|
call_service0 cctxt Services.Blocks.list
|
2017-03-22 20:21:52 +04:00
|
|
|
{ operations ; data ; length ; heads ; monitor = Some false ; delay ;
|
2016-09-21 18:22:43 +04:00
|
|
|
min_date ; min_heads }
|
2017-03-22 20:21:52 +04:00
|
|
|
let monitor cctxt ?(operations = false) ?(data = false)
|
|
|
|
?length ?heads ?delay ?min_date ?min_heads () =
|
2016-12-03 16:05:02 +04:00
|
|
|
call_streamed_service0 cctxt Services.Blocks.list
|
2017-03-22 20:21:52 +04:00
|
|
|
{ operations ; data ; length ; heads ; monitor = Some true ; delay ;
|
2016-09-21 18:22:43 +04:00
|
|
|
min_date ; min_heads }
|
2016-09-08 21:13:10 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module Operations = struct
|
2016-12-03 16:05:02 +04:00
|
|
|
let monitor cctxt ?contents () =
|
|
|
|
call_streamed_service0 cctxt Services.Operations.list
|
2016-09-08 21:13:10 +04:00
|
|
|
{ monitor = Some true ; contents }
|
|
|
|
end
|
2016-10-25 21:00:03 +04:00
|
|
|
|
|
|
|
module Protocols = struct
|
2016-12-03 16:05:02 +04:00
|
|
|
let bytes cctxt hash =
|
|
|
|
call_service1 cctxt Services.Protocols.bytes hash ()
|
|
|
|
let list cctxt ?contents () =
|
|
|
|
call_service0 cctxt Services.Protocols.list { contents; monitor = Some false }
|
2016-10-25 21:00:03 +04:00
|
|
|
end
|
2017-03-02 18:39:36 +04:00
|
|
|
|
|
|
|
module Network = struct
|
|
|
|
let stat cctxt =
|
|
|
|
call_service0 cctxt Services.Network.stat ()
|
|
|
|
let connections cctxt =
|
|
|
|
call_service0 cctxt Services.Network.Connection.list ()
|
|
|
|
let peers cctxt =
|
|
|
|
call_service0 cctxt Services.Network.Peer_id.list []
|
|
|
|
let points cctxt =
|
|
|
|
call_service0 cctxt Services.Network.Point.list []
|
|
|
|
end
|