ligo/src/node/updater/updater.ml

133 lines
4.6 KiB
OCaml
Raw Normal View History

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. *)
(* *)
(**************************************************************************)
open Logging.Updater
let (//) = Filename.concat
type validation_result = Protocol_sigs.validation_result = {
context: Context.t ;
fitness: Fitness.t ;
message: string option ;
max_operations_ttl: int ;
}
type rpc_context = Protocol_sigs.rpc_context = {
block_hash: Block_hash.t ;
block_header: Block_header.t ;
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
operations: unit -> Operation.t list list Lwt.t ;
context: Context.t ;
}
module type PROTOCOL = Protocol_sigs.PROTOCOL
module type PACKED_PROTOCOL = Protocol_sigs.PACKED_PROTOCOL
module type REGISTRED_PROTOCOL = sig
val hash: Protocol_hash.t
include PROTOCOL with type error := error
and type 'a tzresult := 'a tzresult
val complete_b58prefix : Context.t -> string -> string list Lwt.t
end
2016-09-08 21:13:10 +04:00
(** Version table *)
module VersionTable = Protocol_hash.Table
2016-09-08 21:13:10 +04:00
let versions : ((module REGISTRED_PROTOCOL)) VersionTable.t =
VersionTable.create 20
let register hash proto =
VersionTable.add versions hash proto
let activate = Context.set_protocol
let fork_test_network = Context.fork_test_network
let get_exn hash = VersionTable.find versions hash
let get hash =
try Some (get_exn hash)
with Not_found -> None
(** Compiler *)
let datadir = ref None
let get_datadir () =
match !datadir with
2016-09-08 21:13:10 +04:00
| None -> fatal_error "not initialized"
| Some m -> m
let init dir =
datadir := Some dir
2016-09-08 21:13:10 +04:00
let create_files dir units =
Lwt_utils.remove_dir dir >>= fun () ->
Lwt_utils.create_dir dir >>= fun () ->
2016-09-08 21:13:10 +04:00
Lwt_list.map_s
(fun { Protocol.name; interface; implementation } ->
2016-10-25 21:00:03 +04:00
let name = String.lowercase_ascii name in
let ml = dir // (name ^ ".ml") in
let mli = dir // (name ^ ".mli") in
Lwt_utils.create_file ml implementation >>= fun () ->
2016-10-25 21:00:03 +04:00
match interface with
2016-09-08 21:13:10 +04:00
| None -> Lwt.return [ml]
| Some content ->
Lwt_utils.create_file mli content >>= fun () ->
2016-09-08 21:13:10 +04:00
Lwt.return [mli;ml])
units >>= fun files ->
let files = List.concat files in
Lwt.return files
2016-10-25 21:00:03 +04:00
let extract dirname hash units =
let source_dir = dirname // Protocol_hash.to_short_b58check hash // "src" in
2016-10-25 21:00:03 +04:00
create_files source_dir units >|= fun _files ->
Tezos_compiler.Meta.to_file source_dir ~hash
(List.map (fun {Protocol.name} -> String.capitalize_ascii name) units)
2016-10-25 21:00:03 +04:00
2016-09-08 21:13:10 +04:00
let do_compile hash units =
let datadir = get_datadir () in
let source_dir = datadir // Protocol_hash.to_short_b58check hash // "src" in
let log_file = datadir // Protocol_hash.to_short_b58check hash // "LOG" in
let plugin_file = datadir // Protocol_hash.to_short_b58check hash //
2016-10-25 21:00:03 +04:00
Format.asprintf "protocol_%a.cmxs" Protocol_hash.pp hash
in
2016-09-08 21:13:10 +04:00
create_files source_dir units >>= fun _files ->
2016-10-25 21:00:03 +04:00
Tezos_compiler.Meta.to_file source_dir ~hash
(List.map (fun {Protocol.name} -> String.capitalize_ascii name) units);
2016-09-08 21:13:10 +04:00
let compiler_command =
(Sys.executable_name,
Array.of_list [Node_compiler_main.compiler_name; plugin_file; source_dir]) in
let fd = Unix.(openfile log_file [O_WRONLY; O_CREAT; O_TRUNC] 0o644) in
let pi =
Lwt_process.exec
~stdin:`Close ~stdout:(`FD_copy fd) ~stderr:(`FD_move fd)
compiler_command in
pi >>= function
| Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
log_error "INTERRUPTED COMPILATION (%s)" log_file;
Lwt.return false
| Unix.WEXITED x when x <> 0 ->
log_error "COMPILATION ERROR (%s)" log_file;
Lwt.return false
| Unix.WEXITED _ ->
try Dynlink.loadfile_private plugin_file; Lwt.return true
with Dynlink.Error err ->
log_error "Can't load plugin: %s (%s)"
(Dynlink.error_message err) plugin_file;
Lwt.return false
let compile hash units =
if VersionTable.mem versions hash then
Lwt.return true
else begin
do_compile hash units >>= fun success ->
let loaded = VersionTable.mem versions hash in
if success && not loaded then
log_error "Internal error while compiling %a" Protocol_hash.pp hash;
Lwt.return loaded
end