diff --git a/src/bin_signer/handler.ml b/src/bin_signer/handler.ml index 886a7af53..03ac7a386 100644 --- a/src/bin_signer/handler.ml +++ b/src/bin_signer/handler.ml @@ -189,6 +189,18 @@ let deterministic_nonce_hash -% s Client_keys.Logging.tag name) >>= fun () -> Client_keys.deterministic_nonce_hash sk_uri data +let supports_deterministic_nonces (cctxt : #Client_context.wallet) pkh = + log Tag.DSL.(fun f -> + f "Request for checking whether the signer supports deterministic nonces for key %a" + -% t event "request_for_supports_deterministic_nonces" + -% a Signature.Public_key_hash.Logging.tag pkh) >>= fun () -> + Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) -> + log Tag.DSL.(fun f -> + f "Returns true if and only if signer can generate determinstic nonces for key %s" + -% t event "supports_deterministic_nonces" + -% s Client_keys.Logging.tag name) >>= fun () -> + Client_keys.supports_deterministic_nonces sk_uri + let public_key (cctxt : #Client_context.wallet) pkh = log Tag.DSL.(fun f -> f "Request for public key %a" diff --git a/src/bin_signer/handler.mli b/src/bin_signer/handler.mli index 5dea278e0..69ef13d74 100644 --- a/src/bin_signer/handler.mli +++ b/src/bin_signer/handler.mli @@ -55,3 +55,10 @@ val deterministic_nonce_hash : (** [deterministic_nonce_hash cctxt req ~require_auth] generates deterministically a nonce from [req.data] and returns the hash of this nonce. *) + +val supports_deterministic_nonces : + #Client_context.wallet -> + Signature.public_key_hash -> + bool tzresult Lwt.t +(** [supports_deterministic_nonces cctxt pkh] determines whether the + the signer provides the determinsitic nonce functionality. *) diff --git a/src/bin_signer/socket_daemon.ml b/src/bin_signer/socket_daemon.ml index 2102900ac..d7de0b1c0 100644 --- a/src/bin_signer/socket_daemon.ml +++ b/src/bin_signer/socket_daemon.ml @@ -48,6 +48,12 @@ let handle_client ?magic_bytes ~check_high_watermark ~require_auth cctxt fd = Lwt_utils_unix.Socket.send fd encoding res >>= fun _ -> Lwt_unix.close fd >>= fun () -> return_unit + | Supports_deterministic_nonces req -> + let encoding = result_encoding Supports_deterministic_nonces.Response.encoding in + Handler.supports_deterministic_nonces cctxt req >>= fun res -> + Lwt_utils_unix.Socket.send fd encoding res >>= fun _ -> + Lwt_unix.close fd >>= fun () -> + return_unit | Public_key pkh -> let encoding = result_encoding Public_key.Response.encoding in Handler.public_key cctxt pkh >>= fun res -> diff --git a/src/lib_client_base/client_keys.ml b/src/lib_client_base/client_keys.ml index 3f7f74576..bb539da5e 100644 --- a/src/lib_client_base/client_keys.ml +++ b/src/lib_client_base/client_keys.ml @@ -155,6 +155,7 @@ module type SIGNER = sig sk_uri -> MBytes.t -> Signature.t tzresult Lwt.t val deterministic_nonce : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t val deterministic_nonce_hash : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t + val supports_deterministic_nonces : sk_uri -> bool tzresult Lwt.t end let signers_table : (string, (module SIGNER)) Hashtbl.t = Hashtbl.create 13 @@ -246,6 +247,12 @@ let deterministic_nonce_hash sk_uri data = let module Signer = (val signer : SIGNER) in Signer.deterministic_nonce_hash sk_uri data +let supports_deterministic_nonces sk_uri = + let scheme = Option.unopt ~default:"" (Uri.scheme sk_uri) in + find_signer_for_key ~scheme >>=? fun signer -> + let module Signer = (val signer : SIGNER) in + Signer.supports_deterministic_nonces sk_uri + let register_key cctxt ?(force=false) (public_key_hash, pk_uri, sk_uri) ?public_key name = Public_key.add ~force cctxt name (pk_uri, public_key) >>=? fun () -> Secret_key.add ~force cctxt name sk_uri >>=? fun () -> diff --git a/src/lib_client_base/client_keys.mli b/src/lib_client_base/client_keys.mli index bfc3a12cd..e7664f309 100644 --- a/src/lib_client_base/client_keys.mli +++ b/src/lib_client_base/client_keys.mli @@ -100,8 +100,13 @@ module type SIGNER = sig val deterministic_nonce_hash : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t - (** [deterministic_nonce_hash sk data] is a nonce hash obtained - deterministically from [data] and [sk]. *) + (** [deterministic_nonce_hash sk data] is a nonce hash obtained + deterministically from [data] and [sk]. *) + + val supports_deterministic_nonces : sk_uri -> bool tzresult Lwt.t + (** [supports_deterministic_nonces] indicates whether the + [deterministic_nonce] functionality is supported. *) + end val register_signer : (module SIGNER) -> unit @@ -140,6 +145,9 @@ val deterministic_nonce : val deterministic_nonce_hash : sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t +val supports_deterministic_nonces : + sk_uri -> bool tzresult Lwt.t + val register_key : #Client_context.wallet -> ?force:bool -> diff --git a/src/lib_signer_backends/encrypted.ml b/src/lib_signer_backends/encrypted.ml index dceac1cf8..a7835807f 100644 --- a/src/lib_signer_backends/encrypted.ml +++ b/src/lib_signer_backends/encrypted.ml @@ -281,4 +281,6 @@ module Make(C : sig val cctxt: Client_context.prompter end) = struct decrypt C.cctxt sk_uri >>=? fun sk -> return (Signature.deterministic_nonce_hash sk buf) + let supports_deterministic_nonces _ = return_true + end diff --git a/src/lib_signer_backends/http_gen.ml b/src/lib_signer_backends/http_gen.ml index 1a20bfe23..635a8be40 100644 --- a/src/lib_signer_backends/http_gen.ml +++ b/src/lib_signer_backends/http_gen.ml @@ -152,6 +152,18 @@ module Make(N : sig val scheme : string end) = struct signature msg + let supports_deterministic_nonces uri = + parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) -> + RPC_client.call_service + ~logger: P.logger + ?headers + Media_type.all_media_types + ~base Signer_services.supports_deterministic_nonces ((), pkh) () () >>= function + | Ok ans -> return ans + | Error ((RPC_context.Not_found _) :: _) -> return false + | Error _ as res -> Lwt.return res + + end let make_base host port = diff --git a/src/lib_signer_backends/ledger.ml b/src/lib_signer_backends/ledger.ml index dda70ba84..dbd4e62f2 100644 --- a/src/lib_signer_backends/ledger.ml +++ b/src/lib_signer_backends/ledger.ml @@ -496,6 +496,7 @@ let sign ?watermark sk_uri msg = return (Signature.of_p256 signature) end + let deterministic_nonce _ _ = fail Ledger_deterministic_nonce_not_implemented let deterministic_nonce_hash _ _ = fail Ledger_deterministic_nonce_not_implemented let supports_deterministic_nonces _ = return_false diff --git a/src/lib_signer_backends/remote.ml b/src/lib_signer_backends/remote.ml index 98caf625f..86a708e4b 100644 --- a/src/lib_signer_backends/remote.ml +++ b/src/lib_signer_backends/remote.ml @@ -107,6 +107,10 @@ module Make(S : sig (Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t))) msg + let supports_deterministic_nonces sk_uri = + Remote.supports_deterministic_nonces + (Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t))) + end let make_sk sk = diff --git a/src/lib_signer_backends/socket.ml b/src/lib_signer_backends/socket.ml index 718f995cd..6991880b4 100644 --- a/src/lib_signer_backends/socket.ml +++ b/src/lib_signer_backends/socket.ml @@ -96,6 +96,15 @@ module Make(P : sig Lwt_unix.close conn >>= fun () -> Lwt.return res + let supports_deterministic_nonces path pkh = + Lwt_utils_unix.Socket.connect path >>=? fun conn -> + Lwt_utils_unix.Socket.send + conn Request.encoding (Request.Supports_deterministic_nonces pkh) >>=? fun () -> + Lwt_utils_unix.Socket.recv conn + (result_encoding Supports_deterministic_nonces.Response.encoding) >>=? fun res -> + Lwt_unix.close conn >>= fun () -> + Lwt.return res + let public_key path pkh = Lwt_utils_unix.Socket.connect path >>=? fun conn -> Lwt_utils_unix.Socket.send @@ -148,6 +157,10 @@ module Make(P : sig parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) -> deterministic_nonce_hash path pkh msg + let supports_deterministic_nonces uri = + parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) -> + supports_deterministic_nonces path pkh + end module Tcp = struct @@ -202,6 +215,10 @@ module Make(P : sig parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) -> deterministic_nonce_hash path pkh msg + let supports_deterministic_nonces uri = + parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) -> + supports_deterministic_nonces path pkh + end end diff --git a/src/lib_signer_backends/unencrypted.ml b/src/lib_signer_backends/unencrypted.ml index 6909bfad9..52a2f3c98 100644 --- a/src/lib_signer_backends/unencrypted.ml +++ b/src/lib_signer_backends/unencrypted.ml @@ -74,3 +74,5 @@ let deterministic_nonce sk_uri buf = let deterministic_nonce_hash sk_uri buf = secret_key sk_uri >>=? fun sk -> return (Signature.deterministic_nonce_hash sk buf) + +let supports_deterministic_nonces _ = return_true diff --git a/src/lib_signer_services/signer_messages.ml b/src/lib_signer_services/signer_messages.ml index 54e430779..6b0c52898 100644 --- a/src/lib_signer_services/signer_messages.ml +++ b/src/lib_signer_services/signer_messages.ml @@ -116,6 +116,27 @@ module Deterministic_nonce_hash = struct end +module Supports_deterministic_nonces = struct + + module Request = struct + + type t = Signature.Public_key_hash.t + + let encoding = + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + + end + + module Response = struct + + type t = bool + + let encoding = Data_encoding.(obj1 (req "bool" bool)) + end + +end + + module Public_key = struct @@ -173,6 +194,7 @@ module Request = struct | Authorized_keys | Deterministic_nonce of Deterministic_nonce.Request.t | Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t + | Supports_deterministic_nonces of Supports_deterministic_nonces.Request.t let encoding = let open Data_encoding in @@ -210,6 +232,13 @@ module Request = struct Deterministic_nonce_hash.Request.encoding) (function Deterministic_nonce_hash req -> Some ((), req) | _ -> None) (fun ((), req) -> Deterministic_nonce_hash req) ; + case (Tag 5) + ~title:"Supports_deterministic_nonces" + (merge_objs + (obj1 (req "kind" (constant "supports_deterministic_nonces"))) + Supports_deterministic_nonces.Request.encoding) + (function Supports_deterministic_nonces req -> Some ((), req) | _ -> None) + (fun ((), req) -> Supports_deterministic_nonces req) ; ] end diff --git a/src/lib_signer_services/signer_messages.mli b/src/lib_signer_services/signer_messages.mli index 8450214cf..2a0f0794c 100644 --- a/src/lib_signer_services/signer_messages.mli +++ b/src/lib_signer_services/signer_messages.mli @@ -69,6 +69,20 @@ module Deterministic_nonce_hash : sig end +module Supports_deterministic_nonces : sig + + module Request : sig + type t = Signature.Public_key_hash.t + val encoding : t Data_encoding.t + end + + module Response : sig + type t = bool + val encoding : t Data_encoding.t + end + +end + module Public_key : sig module Request : sig @@ -103,6 +117,7 @@ module Request : sig | Authorized_keys | Deterministic_nonce of Deterministic_nonce.Request.t | Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t + | Supports_deterministic_nonces of Supports_deterministic_nonces.Request.t val encoding : t Data_encoding.t end diff --git a/src/lib_signer_services/signer_services.ml b/src/lib_signer_services/signer_services.ml index 902305673..694125b08 100644 --- a/src/lib_signer_services/signer_services.ml +++ b/src/lib_signer_services/signer_services.ml @@ -59,6 +59,13 @@ let deterministic_nonce_hash = ~output: Data_encoding.(obj1 (req "deterministic_nonce_hash" bytes)) RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg) +let supports_deterministic_nonces = + RPC_service.get_service + ~description: "Obtain whether the signing service suppports the determinstic nonces functionality" + ~query: RPC_query.empty + ~output: Data_encoding.(obj1 (req "supports_deterministic_nonces" bool)) + RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg) + let public_key = RPC_service.get_service ~description: "Retrieve the public key of a given remote key" diff --git a/src/lib_signer_services/signer_services.mli b/src/lib_signer_services/signer_services.mli index d8b850e2f..2785dec0e 100644 --- a/src/lib_signer_services/signer_services.mli +++ b/src/lib_signer_services/signer_services.mli @@ -35,6 +35,10 @@ val deterministic_nonce_hash : ([ `POST ], unit, unit * Signature.Public_key_hash.t, Signature.t option, MBytes.t, MBytes.t) RPC_service.t +val supports_deterministic_nonces : + ([ `GET ], unit, unit * Signature.Public_key_hash.t, + unit, unit, bool) RPC_service.t + val public_key : ([ `GET ], unit, unit * Signature.Public_key_hash.t, unit, unit, Signature.Public_key.t) RPC_service.t