(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2019 Nomadic Labs, *) (* *) (* 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 Filename.Infix let get_config data_dir config_file expected_pow = let open Lwt_result_syntax in let* cfg = match (data_dir, config_file) with | None, None -> let default_config = Node_config_file.default_data_dir // Node_data_version.default_config_file_name in let*! config_file_exists = Lwt_unix.file_exists default_config in if config_file_exists then Node_config_file.read default_config else return Node_config_file.default_config | None, Some config_file -> Node_config_file.read config_file | Some data_dir, None -> let* cfg = Node_config_file.read (data_dir // Node_data_version.default_config_file_name) in return {cfg with data_dir} | Some data_dir, Some config_file -> let* cfg = Node_config_file.read config_file in return {cfg with data_dir} in Node_config_file.update ?expected_pow cfg (** Commands *) let identity_file data_dir = data_dir // Node_data_version.default_identity_file_name let show data_dir config_file expected_pow = Node_shared_arg.process_command (let open Lwt_result_syntax in let* {Node_config_file.data_dir; _} = get_config data_dir config_file expected_pow in let* id = Node_identity_file.read (identity_file data_dir) in Format.printf "Peer_id: %a.@." P2p_peer.Id.pp id.peer_id ; return_unit) let check data_dir config_file expected_pow = Node_shared_arg.process_command (let open Lwt_result_syntax in let* {Node_config_file.data_dir; p2p = {expected_pow; _}; _} = get_config data_dir config_file expected_pow in let* id = Node_identity_file.read ~expected_pow (identity_file data_dir) in Format.printf "Peer_id: %a. Proof of work is higher than %.2f.@." P2p_peer.Id.pp id.peer_id expected_pow ; return_unit) let generate data_dir config_file expected_pow = Node_shared_arg.process_command (let open Lwt_result_syntax in let* {Node_config_file.data_dir; p2p = {expected_pow; _}; _} = get_config data_dir config_file expected_pow in let* _id = Node_identity_file.generate (identity_file data_dir) expected_pow in return_unit) (** Main *) module Term = struct let expected_pow = let open Cmdliner in let doc = "Expected amount of proof-of-work for the node identity. The optional \ parameter should be a float between 0 and 256, where\n\ \ 0 disables the proof-of-work mechanism." in Arg.(value & pos 0 (some float) None & info [] ~docv:"DIFFICULTY" ~doc) let cmds = [ Cmdliner.Cmd.v (Cmdliner.Cmd.info ~doc: "reads, parses and displays the current identity of the node. Use \ this command to see what identity will be used by Tezos. This is \ the default operation" "show") Cmdliner.Term.( ret (const show $ Node_shared_arg.Term.data_dir $ Node_shared_arg.Term.config_file $ expected_pow)); Cmdliner.Cmd.v (Cmdliner.Cmd.info ~doc: "generates an identity whose proof of work stamp difficulty is at \ least equal to $(i,difficulty). The value provided must be a \ floating point number between 0 and 256. It roughly reflects the \ numbers of expected leading zeroes in the hash of the identity \ data-structure. Therefore, a value of 0 means no proof-of-work, \ and the difficulty doubles for each increment of 1 in the \ difficulty value" "generate") Cmdliner.Term.( ret (const generate $ Node_shared_arg.Term.data_dir $ Node_shared_arg.Term.config_file $ expected_pow)); Cmdliner.Cmd.v (Cmdliner.Cmd.info ~doc: "checks that an identity is valid and that its proof of work \ stamp difficulty is at least equal to $(i,difficulty)" "check") Cmdliner.Term.( ret (const check $ Node_shared_arg.Term.data_dir $ Node_shared_arg.Term.config_file $ expected_pow)); ] end module Manpage = struct let command_description = "The $(b,identity) command is meant to create and manage node identities. \ An $(i,identity) uniquely identifies a peer on the network and consists \ of a cryptographic key pair as well as a proof-of-work stamp that \ certifies that enough CPU time has been dedicated to produce the \ identity, to avoid sybil attacks. An identity with enough proof-of-work \ is required to participate in the Tezos network, therefore this command \ is necessary to launch Tezos the first time." let man = (* [ `S misc_docs ] @ *) Node_shared_arg.Manpage.bugs let info = Cmdliner.Cmd.info ~doc:"Manage node identities" ~man "identity" end let cmd = Cmdliner.Cmd.group Manpage.info Term.cmds