Signer: added deterministic nonces
This commit is contained in:
parent
987d3a9c6a
commit
fd9694d8b0
@ -116,18 +116,9 @@ let check_magic_byte magic_bytes data =
|
|||||||
else
|
else
|
||||||
failwith "magic byte 0x%02X not allowed" byte
|
failwith "magic byte 0x%02X not allowed" byte
|
||||||
|
|
||||||
let sign
|
|
||||||
(cctxt : #Client_context.wallet)
|
let check_authorization cctxt pkh data require_auth signature =
|
||||||
Signer_messages.Sign.Request.{ pkh ; data ; signature }
|
match require_auth, signature with
|
||||||
?magic_bytes ~check_high_watermark ~require_auth =
|
|
||||||
log Tag.DSL.(fun f ->
|
|
||||||
f "Request for signing %d bytes of data for key %a, magic byte = %02X"
|
|
||||||
-% t event "request_for_signing"
|
|
||||||
-% s num_bytes (MBytes.length data)
|
|
||||||
-% a Signature.Public_key_hash.Logging.tag pkh
|
|
||||||
-% s magic_byte (MBytes.get_uint8 data 0)) >>= fun () ->
|
|
||||||
check_magic_byte magic_bytes data >>=? fun () ->
|
|
||||||
begin match require_auth, signature with
|
|
||||||
| false, _ -> return_unit
|
| false, _ -> return_unit
|
||||||
| true, None -> failwith "missing authentication signature field"
|
| true, None -> failwith "missing authentication signature field"
|
||||||
| true, Some signature ->
|
| true, Some signature ->
|
||||||
@ -140,7 +131,19 @@ let sign
|
|||||||
return_unit
|
return_unit
|
||||||
else
|
else
|
||||||
failwith "invalid authentication signature"
|
failwith "invalid authentication signature"
|
||||||
end >>=? fun () ->
|
|
||||||
|
let sign
|
||||||
|
(cctxt : #Client_context.wallet)
|
||||||
|
Signer_messages.Sign.Request.{ pkh ; data ; signature }
|
||||||
|
?magic_bytes ~check_high_watermark ~require_auth =
|
||||||
|
log Tag.DSL.(fun f ->
|
||||||
|
f "Request for signing %d bytes of data for key %a, magic byte = %02X"
|
||||||
|
-% t event "request_for_signing"
|
||||||
|
-% s num_bytes (MBytes.length data)
|
||||||
|
-% a Signature.Public_key_hash.Logging.tag pkh
|
||||||
|
-% s magic_byte (MBytes.get_uint8 data 0)) >>= fun () ->
|
||||||
|
check_magic_byte magic_bytes data >>=? fun () ->
|
||||||
|
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||||
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||||
log Tag.DSL.(fun f ->
|
log Tag.DSL.(fun f ->
|
||||||
f "Signing data for key %s"
|
f "Signing data for key %s"
|
||||||
@ -152,6 +155,40 @@ let sign
|
|||||||
else
|
else
|
||||||
sign data
|
sign data
|
||||||
|
|
||||||
|
let deterministic_nonce
|
||||||
|
(cctxt : #Client_context.wallet)
|
||||||
|
Signer_messages.Deterministic_nonce.Request.{ pkh ; data ; signature }
|
||||||
|
~require_auth =
|
||||||
|
log Tag.DSL.(fun f ->
|
||||||
|
f "Request for creating a nonce from %d input bytes for key %a"
|
||||||
|
-% t event "request_for_deterministic_nonce"
|
||||||
|
-% s num_bytes (MBytes.length data)
|
||||||
|
-% a Signature.Public_key_hash.Logging.tag pkh) >>= fun () ->
|
||||||
|
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||||
|
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||||
|
log Tag.DSL.(fun f ->
|
||||||
|
f "Creating nonce for key %s"
|
||||||
|
-% t event "creating_nonce"
|
||||||
|
-% s Client_keys.Logging.tag name) >>= fun () ->
|
||||||
|
Client_keys.deterministic_nonce sk_uri data
|
||||||
|
|
||||||
|
let deterministic_nonce_hash
|
||||||
|
(cctxt : #Client_context.wallet)
|
||||||
|
Signer_messages.Deterministic_nonce_hash.Request.{ pkh ; data ; signature }
|
||||||
|
~require_auth =
|
||||||
|
log Tag.DSL.(fun f ->
|
||||||
|
f "Request for creating a nonce hash from %d input bytes for key %a"
|
||||||
|
-% t event "request_for_deterministic_nonce_hash"
|
||||||
|
-% s num_bytes (MBytes.length data)
|
||||||
|
-% a Signature.Public_key_hash.Logging.tag pkh) >>= fun () ->
|
||||||
|
check_authorization cctxt pkh data require_auth signature >>=? fun () ->
|
||||||
|
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||||
|
log Tag.DSL.(fun f ->
|
||||||
|
f "Creating nonce hash for key %s"
|
||||||
|
-% t event "creating_nonce_hash"
|
||||||
|
-% s Client_keys.Logging.tag name) >>= fun () ->
|
||||||
|
Client_keys.deterministic_nonce_hash sk_uri data
|
||||||
|
|
||||||
let public_key (cctxt : #Client_context.wallet) pkh =
|
let public_key (cctxt : #Client_context.wallet) pkh =
|
||||||
log Tag.DSL.(fun f ->
|
log Tag.DSL.(fun f ->
|
||||||
f "Request for public key %a"
|
f "Request for public key %a"
|
||||||
|
@ -40,3 +40,18 @@ val sign :
|
|||||||
check_high_watermark:bool -> require_auth:bool -> Signature.t tzresult Lwt.t
|
check_high_watermark:bool -> require_auth:bool -> Signature.t tzresult Lwt.t
|
||||||
(** [sign cctxt req ?magic_bytes ~check_high_watermark ~require_auth]
|
(** [sign cctxt req ?magic_bytes ~check_high_watermark ~require_auth]
|
||||||
signs [req] and returns a signature. *)
|
signs [req] and returns a signature. *)
|
||||||
|
|
||||||
|
val deterministic_nonce :
|
||||||
|
#Client_context.wallet ->
|
||||||
|
Signer_messages.Deterministic_nonce.Request.t ->
|
||||||
|
require_auth:bool -> MBytes.t tzresult Lwt.t
|
||||||
|
(** [deterministic_nonce cctxt req ~require_auth] generates
|
||||||
|
deterministically a nonce from [req.data]. *)
|
||||||
|
|
||||||
|
val deterministic_nonce_hash :
|
||||||
|
#Client_context.wallet ->
|
||||||
|
Signer_messages.Deterministic_nonce_hash.Request.t ->
|
||||||
|
require_auth:bool -> MBytes.t tzresult Lwt.t
|
||||||
|
(** [deterministic_nonce_hash cctxt req ~require_auth] generates
|
||||||
|
deterministically a nonce from [req.data] and returns the hash of
|
||||||
|
this nonce. *)
|
||||||
|
@ -224,7 +224,7 @@ let commands base_dir require_auth =
|
|||||||
(prefixes [ "launch" ; "https" ; "signer" ] @@
|
(prefixes [ "launch" ; "https" ; "signer" ] @@
|
||||||
param
|
param
|
||||||
~name:"cert"
|
~name:"cert"
|
||||||
~desc: "path to th TLS certificate"
|
~desc: "path to the TLS certificate"
|
||||||
(parameter (fun _ s ->
|
(parameter (fun _ s ->
|
||||||
if not (Sys.file_exists s) then
|
if not (Sys.file_exists s) then
|
||||||
failwith "No such TLS certificate file %s" s
|
failwith "No such TLS certificate file %s" s
|
||||||
@ -232,7 +232,7 @@ let commands base_dir require_auth =
|
|||||||
return s)) @@
|
return s)) @@
|
||||||
param
|
param
|
||||||
~name:"key"
|
~name:"key"
|
||||||
~desc: "path to th TLS key"
|
~desc: "path to the TLS key"
|
||||||
(parameter (fun _ s ->
|
(parameter (fun _ s ->
|
||||||
if not (Sys.file_exists s) then
|
if not (Sys.file_exists s) then
|
||||||
failwith "No such TLS key file %s" s
|
failwith "No such TLS key file %s" s
|
||||||
|
@ -36,6 +36,18 @@ let handle_client ?magic_bytes ~check_high_watermark ~require_auth cctxt fd =
|
|||||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||||
Lwt_unix.close fd >>= fun () ->
|
Lwt_unix.close fd >>= fun () ->
|
||||||
return_unit
|
return_unit
|
||||||
|
| Deterministic_nonce req ->
|
||||||
|
let encoding = result_encoding Deterministic_nonce.Response.encoding in
|
||||||
|
Handler.deterministic_nonce cctxt req ~require_auth >>= fun res ->
|
||||||
|
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||||
|
Lwt_unix.close fd >>= fun () ->
|
||||||
|
return_unit
|
||||||
|
| Deterministic_nonce_hash req ->
|
||||||
|
let encoding = result_encoding Deterministic_nonce_hash.Response.encoding in
|
||||||
|
Handler.deterministic_nonce_hash cctxt req ~require_auth >>= fun res ->
|
||||||
|
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||||
|
Lwt_unix.close fd >>= fun () ->
|
||||||
|
return_unit
|
||||||
| Public_key pkh ->
|
| Public_key pkh ->
|
||||||
let encoding = result_encoding Public_key.Response.encoding in
|
let encoding = result_encoding Public_key.Response.encoding in
|
||||||
Handler.public_key cctxt pkh >>= fun res ->
|
Handler.public_key cctxt pkh >>= fun res ->
|
||||||
|
@ -153,6 +153,8 @@ module type SIGNER = sig
|
|||||||
val sign :
|
val sign :
|
||||||
?watermark: Signature.watermark ->
|
?watermark: Signature.watermark ->
|
||||||
sk_uri -> MBytes.t -> Signature.t tzresult Lwt.t
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
let signers_table : (string, (module SIGNER)) Hashtbl.t = Hashtbl.create 13
|
let signers_table : (string, (module SIGNER)) Hashtbl.t = Hashtbl.create 13
|
||||||
@ -232,6 +234,18 @@ let check ?watermark pk_uri signature buf =
|
|||||||
public_key pk_uri >>=? fun pk ->
|
public_key pk_uri >>=? fun pk ->
|
||||||
return (Signature.check ?watermark pk signature buf)
|
return (Signature.check ?watermark pk signature buf)
|
||||||
|
|
||||||
|
let deterministic_nonce sk_uri data =
|
||||||
|
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.deterministic_nonce sk_uri data
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk_uri data =
|
||||||
|
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.deterministic_nonce_hash sk_uri data
|
||||||
|
|
||||||
let register_key cctxt ?(force=false) (public_key_hash, pk_uri, sk_uri) ?public_key name =
|
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 () ->
|
Public_key.add ~force cctxt name (pk_uri, public_key) >>=? fun () ->
|
||||||
Secret_key.add ~force cctxt name sk_uri >>=? fun () ->
|
Secret_key.add ~force cctxt name sk_uri >>=? fun () ->
|
||||||
|
@ -93,6 +93,15 @@ module type SIGNER = sig
|
|||||||
(** [sign ?watermark sk data] is signature obtained by signing [data] with
|
(** [sign ?watermark sk data] is signature obtained by signing [data] with
|
||||||
[sk]. *)
|
[sk]. *)
|
||||||
|
|
||||||
|
val deterministic_nonce :
|
||||||
|
sk_uri -> MBytes.t -> MBytes.t tzresult Lwt.t
|
||||||
|
(** [deterministic_nonce sk data] is a nonce obtained
|
||||||
|
deterministically from [data] and [sk]. *)
|
||||||
|
|
||||||
|
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]. *)
|
||||||
end
|
end
|
||||||
|
|
||||||
val register_signer : (module SIGNER) -> unit
|
val register_signer : (module SIGNER) -> unit
|
||||||
@ -125,6 +134,12 @@ val check :
|
|||||||
?watermark:Signature.watermark ->
|
?watermark:Signature.watermark ->
|
||||||
pk_uri -> Signature.t -> MBytes.t -> bool tzresult Lwt.t
|
pk_uri -> Signature.t -> MBytes.t -> bool 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 register_key :
|
val register_key :
|
||||||
#Client_context.wallet ->
|
#Client_context.wallet ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
@ -160,4 +175,3 @@ val force_switch : unit -> (bool, 'ctx) Clic.arg
|
|||||||
|
|
||||||
val make_pk_uri : Uri.t -> pk_uri
|
val make_pk_uri : Uri.t -> pk_uri
|
||||||
val make_sk_uri : Uri.t -> sk_uri
|
val make_sk_uri : Uri.t -> sk_uri
|
||||||
|
|
||||||
|
@ -343,6 +343,14 @@ let generate_key ?seed () =
|
|||||||
let pk = Sign.neuterize sk in
|
let pk = Sign.neuterize sk in
|
||||||
Public_key.hash pk, pk, sk
|
Public_key.hash pk, pk, sk
|
||||||
|
|
||||||
|
|
||||||
|
let deterministic_nonce sk msg =
|
||||||
|
Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk msg =
|
||||||
|
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||||
|
|
||||||
|
|
||||||
include Compare.Make(struct
|
include Compare.Make(struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
let compare = MBytes.compare
|
let compare = MBytes.compare
|
||||||
|
@ -282,6 +282,13 @@ let generate_key ?(seed=Rand.generate 32) () =
|
|||||||
let pkh = Public_key.hash pk in
|
let pkh = Public_key.hash pk in
|
||||||
pkh, pk, sk
|
pkh, pk, sk
|
||||||
|
|
||||||
|
let deterministic_nonce sk msg =
|
||||||
|
Hacl.Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk msg =
|
||||||
|
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||||
|
|
||||||
|
|
||||||
include Compare.Make(struct
|
include Compare.Make(struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
let compare = MBytes.compare
|
let compare = MBytes.compare
|
||||||
|
@ -247,4 +247,8 @@ module type SIGNATURE = sig
|
|||||||
|
|
||||||
val generate_key: ?seed:MBytes.t -> unit -> (Public_key_hash.t * Public_key.t * Secret_key.t)
|
val generate_key: ?seed:MBytes.t -> unit -> (Public_key_hash.t * Public_key.t * Secret_key.t)
|
||||||
|
|
||||||
|
val deterministic_nonce: Secret_key.t -> MBytes.t -> MBytes.t
|
||||||
|
|
||||||
|
val deterministic_nonce_hash: Secret_key.t -> MBytes.t -> MBytes.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -285,3 +285,9 @@ let generate_key ?(seed=Rand.generate 32) () =
|
|||||||
let pk = Key.neuterize_exn context sk in
|
let pk = Key.neuterize_exn context sk in
|
||||||
let pkh = Public_key.hash pk in
|
let pkh = Public_key.hash pk in
|
||||||
pkh, pk, sk
|
pkh, pk, sk
|
||||||
|
|
||||||
|
let deterministic_nonce sk msg =
|
||||||
|
Hacl.Hash.SHA256.HMAC.digest ~key: (Secret_key.to_bytes sk) ~msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk msg =
|
||||||
|
Blake2B.to_bytes (Blake2B.hash_bytes [deterministic_nonce sk msg])
|
||||||
|
@ -601,3 +601,15 @@ let generate_key ?(algo = Ed25519) ?seed () =
|
|||||||
let pkh, pk, sk = P256.generate_key ?seed () in
|
let pkh, pk, sk = P256.generate_key ?seed () in
|
||||||
(Public_key_hash.P256 pkh,
|
(Public_key_hash.P256 pkh,
|
||||||
Public_key.P256 pk, Secret_key.P256 sk)
|
Public_key.P256 pk, Secret_key.P256 sk)
|
||||||
|
|
||||||
|
let deterministic_nonce sk msg =
|
||||||
|
match sk with
|
||||||
|
| Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg
|
||||||
|
| Secret_key.Secp256k1 sk -> Secp256k1.deterministic_nonce sk msg
|
||||||
|
| Secret_key.P256 sk -> P256.deterministic_nonce sk msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk msg =
|
||||||
|
match sk with
|
||||||
|
| Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce_hash sk msg
|
||||||
|
| Secret_key.Secp256k1 sk -> Secp256k1.deterministic_nonce_hash sk msg
|
||||||
|
| Secret_key.P256 sk -> P256.deterministic_nonce_hash sk msg
|
||||||
|
@ -262,12 +262,23 @@ module Make(C : sig val cctxt: Client_context.prompter end) = struct
|
|||||||
where <public_key> is the public key in Base58."
|
where <public_key> is the public key in Base58."
|
||||||
|
|
||||||
let public_key = Unencrypted.public_key
|
let public_key = Unencrypted.public_key
|
||||||
|
|
||||||
let public_key_hash = Unencrypted.public_key_hash
|
let public_key_hash = Unencrypted.public_key_hash
|
||||||
|
|
||||||
let neuterize sk_uri =
|
let neuterize sk_uri =
|
||||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||||
return (Unencrypted.make_pk (Signature.Secret_key.to_public_key sk))
|
return (Unencrypted.make_pk (Signature.Secret_key.to_public_key sk))
|
||||||
|
|
||||||
let sign ?watermark sk_uri buf =
|
let sign ?watermark sk_uri buf =
|
||||||
decrypt C.cctxt sk_uri >>=? fun sk ->
|
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||||
return (Signature.sign ?watermark sk buf)
|
return (Signature.sign ?watermark sk buf)
|
||||||
|
|
||||||
|
let deterministic_nonce sk_uri buf =
|
||||||
|
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||||
|
return (Signature.deterministic_nonce sk buf)
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk_uri buf =
|
||||||
|
decrypt C.cctxt sk_uri >>=? fun sk ->
|
||||||
|
return (Signature.deterministic_nonce_hash sk buf)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -100,6 +100,20 @@ module Make(N : sig val scheme : string end) = struct
|
|||||||
public_key ?interactive uri >>=? fun pk ->
|
public_key ?interactive uri >>=? fun pk ->
|
||||||
return (Signature.Public_key.hash pk, Some pk)
|
return (Signature.Public_key.hash pk, Some pk)
|
||||||
|
|
||||||
|
let get_signature base pkh msg =
|
||||||
|
RPC_client.call_service
|
||||||
|
~logger: P.logger
|
||||||
|
?headers
|
||||||
|
Media_type.all_media_types
|
||||||
|
~base Signer_services.authorized_keys () () ()
|
||||||
|
>>=? function
|
||||||
|
| Some authorized_keys ->
|
||||||
|
P.authenticate
|
||||||
|
authorized_keys
|
||||||
|
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||||
|
return_some signature
|
||||||
|
| None -> return_none
|
||||||
|
|
||||||
let sign ?watermark uri msg =
|
let sign ?watermark uri msg =
|
||||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||||
let msg =
|
let msg =
|
||||||
@ -107,19 +121,7 @@ module Make(N : sig val scheme : string end) = struct
|
|||||||
| None -> msg
|
| None -> msg
|
||||||
| Some watermark ->
|
| Some watermark ->
|
||||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||||
RPC_client.call_service
|
get_signature base pkh msg >>=? fun signature ->
|
||||||
~logger: P.logger
|
|
||||||
?headers
|
|
||||||
Media_type.all_media_types
|
|
||||||
~base Signer_services.authorized_keys () () () >>=? fun authorized_keys ->
|
|
||||||
begin match authorized_keys with
|
|
||||||
| Some authorized_keys ->
|
|
||||||
P.authenticate
|
|
||||||
authorized_keys
|
|
||||||
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
|
||||||
return_some signature
|
|
||||||
| None -> return_none
|
|
||||||
end >>=? fun signature ->
|
|
||||||
RPC_client.call_service
|
RPC_client.call_service
|
||||||
~logger: P.logger
|
~logger: P.logger
|
||||||
?headers
|
?headers
|
||||||
@ -128,6 +130,28 @@ module Make(N : sig val scheme : string end) = struct
|
|||||||
signature
|
signature
|
||||||
msg
|
msg
|
||||||
|
|
||||||
|
let deterministic_nonce uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||||
|
get_signature base pkh msg >>=? fun signature ->
|
||||||
|
RPC_client.call_service
|
||||||
|
~logger: P.logger
|
||||||
|
?headers
|
||||||
|
Media_type.all_media_types
|
||||||
|
~base Signer_services.deterministic_nonce ((), pkh)
|
||||||
|
signature
|
||||||
|
msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||||
|
get_signature base pkh msg >>=? fun signature ->
|
||||||
|
RPC_client.call_service
|
||||||
|
~logger: P.logger
|
||||||
|
?headers
|
||||||
|
Media_type.all_media_types
|
||||||
|
~base Signer_services.deterministic_nonce_hash ((), pkh)
|
||||||
|
signature
|
||||||
|
msg
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let make_base host port =
|
let make_base host port =
|
||||||
|
@ -105,6 +105,7 @@ let secp256k1_ctx =
|
|||||||
|
|
||||||
type error +=
|
type error +=
|
||||||
| LedgerError of Ledgerwallet.Transport.error
|
| LedgerError of Ledgerwallet.Transport.error
|
||||||
|
| Ledger_deterministic_nonce_not_implemented
|
||||||
|
|
||||||
let error_encoding =
|
let error_encoding =
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
@ -125,6 +126,20 @@ let () =
|
|||||||
(function LedgerError e -> Some e | _ -> None)
|
(function LedgerError e -> Some e | _ -> None)
|
||||||
(fun e -> LedgerError e)
|
(fun e -> LedgerError e)
|
||||||
|
|
||||||
|
let () =
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id: "signer.ledger.deterministic_nonce_not_implemented"
|
||||||
|
~title: "Ledger deterministic_nonce(_hash) not implemented"
|
||||||
|
~description: "The deterministic_nonce(_hash) functionality \
|
||||||
|
is not implemented by the ledger"
|
||||||
|
~pp:(fun ppf () ->
|
||||||
|
Format.fprintf ppf "Asked the ledger to generate a deterministic nonce (hash), \
|
||||||
|
but this functionality is not yet implemented")
|
||||||
|
Data_encoding.unit
|
||||||
|
(function Ledger_deterministic_nonce_not_implemented -> Some () | _ -> None)
|
||||||
|
(fun () -> Ledger_deterministic_nonce_not_implemented)
|
||||||
|
|
||||||
type id =
|
type id =
|
||||||
| Animals of Ledger_names.t * Ledgerwallet_tezos.curve option
|
| Animals of Ledger_names.t * Ledgerwallet_tezos.curve option
|
||||||
| Pkh of Signature.Public_key_hash.t
|
| Pkh of Signature.Public_key_hash.t
|
||||||
@ -481,6 +496,10 @@ let sign ?watermark sk_uri msg =
|
|||||||
return (Signature.of_p256 signature)
|
return (Signature.of_p256 signature)
|
||||||
end
|
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
|
||||||
|
|
||||||
let commands =
|
let commands =
|
||||||
let open Clic in
|
let open Clic in
|
||||||
let group =
|
let group =
|
||||||
|
@ -97,6 +97,16 @@ module Make(S : sig
|
|||||||
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||||
msg
|
msg
|
||||||
|
|
||||||
|
let deterministic_nonce sk_uri msg =
|
||||||
|
Remote.deterministic_nonce
|
||||||
|
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||||
|
msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk_uri msg =
|
||||||
|
Remote.deterministic_nonce_hash
|
||||||
|
(Client_keys.make_sk_uri (key (sk_uri : sk_uri :> Uri.t)))
|
||||||
|
msg
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let make_sk sk =
|
let make_sk sk =
|
||||||
@ -186,4 +196,3 @@ let parse_base_uri s =
|
|||||||
| Some scheme -> failwith "Unknown scheme: %s" scheme
|
| Some scheme -> failwith "Unknown scheme: %s" scheme
|
||||||
| None -> failwith "Unknown scheme: <empty>"
|
| None -> failwith "Unknown scheme: <empty>"
|
||||||
with Invalid_argument msg -> failwith "Malformed URI: %s" msg
|
with Invalid_argument msg -> failwith "Malformed URI: %s" msg
|
||||||
|
|
||||||
|
@ -33,12 +33,22 @@ module Make(P : sig
|
|||||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||||
end) = struct
|
end) = struct
|
||||||
|
|
||||||
let sign ?watermark path pkh msg =
|
type request_type =
|
||||||
let msg =
|
| Sign_request
|
||||||
match watermark with
|
| Deterministic_nonce_request
|
||||||
| None -> msg
|
| Deterministic_nonce_hash_request
|
||||||
| Some watermark ->
|
|
||||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
let build_request pkh data signature = function
|
||||||
|
| Sign_request ->
|
||||||
|
Request.Sign { Sign.Request.pkh ; data ; signature }
|
||||||
|
| Deterministic_nonce_request ->
|
||||||
|
Request.Deterministic_nonce
|
||||||
|
{ Deterministic_nonce.Request.pkh ; data ; signature }
|
||||||
|
| Deterministic_nonce_hash_request ->
|
||||||
|
Request.Deterministic_nonce_hash
|
||||||
|
{ Deterministic_nonce_hash.Request.pkh ; data ; signature }
|
||||||
|
|
||||||
|
let signer_operation path pkh msg request_type =
|
||||||
begin
|
begin
|
||||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||||
Lwt_utils_unix.Socket.send
|
Lwt_utils_unix.Socket.send
|
||||||
@ -55,15 +65,37 @@ module Make(P : sig
|
|||||||
return_some signature
|
return_some signature
|
||||||
end
|
end
|
||||||
end >>=? fun signature ->
|
end >>=? fun signature ->
|
||||||
let req = { Sign.Request.pkh ; data = msg ; signature } in
|
|
||||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||||
Lwt_utils_unix.Socket.send
|
let req = build_request pkh msg signature request_type in
|
||||||
conn Request.encoding (Request.Sign req) >>=? fun () ->
|
Lwt_utils_unix.Socket.send conn Request.encoding req >>=? fun () ->
|
||||||
|
return conn
|
||||||
|
|
||||||
|
let sign ?watermark path pkh msg =
|
||||||
|
let msg =
|
||||||
|
match watermark with
|
||||||
|
| None -> msg
|
||||||
|
| Some watermark ->
|
||||||
|
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||||
|
signer_operation path pkh msg Sign_request >>=? fun conn ->
|
||||||
Lwt_utils_unix.Socket.recv conn
|
Lwt_utils_unix.Socket.recv conn
|
||||||
(result_encoding Sign.Response.encoding) >>=? fun res ->
|
(result_encoding Sign.Response.encoding) >>=? fun res ->
|
||||||
Lwt_unix.close conn >>= fun () ->
|
Lwt_unix.close conn >>= fun () ->
|
||||||
Lwt.return res
|
Lwt.return res
|
||||||
|
|
||||||
|
let deterministic_nonce path pkh msg =
|
||||||
|
signer_operation path pkh msg Deterministic_nonce_request >>=? fun conn ->
|
||||||
|
Lwt_utils_unix.Socket.recv conn
|
||||||
|
(result_encoding Deterministic_nonce.Response.encoding) >>=? fun res ->
|
||||||
|
Lwt_unix.close conn >>= fun () ->
|
||||||
|
Lwt.return res
|
||||||
|
|
||||||
|
let deterministic_nonce_hash path pkh msg =
|
||||||
|
signer_operation path pkh msg Deterministic_nonce_hash_request >>=? fun conn ->
|
||||||
|
Lwt_utils_unix.Socket.recv conn
|
||||||
|
(result_encoding Deterministic_nonce_hash.Response.encoding) >>=? fun res ->
|
||||||
|
Lwt_unix.close conn >>= fun () ->
|
||||||
|
Lwt.return res
|
||||||
|
|
||||||
let public_key path pkh =
|
let public_key path pkh =
|
||||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||||
Lwt_utils_unix.Socket.send
|
Lwt_utils_unix.Socket.send
|
||||||
@ -108,6 +140,14 @@ module Make(P : sig
|
|||||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
sign ?watermark path pkh msg
|
sign ?watermark path pkh msg
|
||||||
|
|
||||||
|
let deterministic_nonce uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
|
deterministic_nonce path pkh msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
|
deterministic_nonce_hash path pkh msg
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Tcp = struct
|
module Tcp = struct
|
||||||
@ -154,6 +194,14 @@ module Make(P : sig
|
|||||||
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
sign ?watermark path pkh msg
|
sign ?watermark path pkh msg
|
||||||
|
|
||||||
|
let deterministic_nonce uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
|
deterministic_nonce path pkh msg
|
||||||
|
|
||||||
|
let deterministic_nonce_hash uri msg =
|
||||||
|
parse (uri : sk_uri :> Uri.t) >>=? fun (path, pkh) ->
|
||||||
|
deterministic_nonce_hash path pkh msg
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -66,3 +66,11 @@ let public_key_hash ?interactive pk_uri =
|
|||||||
let sign ?watermark sk_uri buf =
|
let sign ?watermark sk_uri buf =
|
||||||
secret_key sk_uri >>=? fun sk ->
|
secret_key sk_uri >>=? fun sk ->
|
||||||
return (Signature.sign ?watermark sk buf)
|
return (Signature.sign ?watermark sk buf)
|
||||||
|
|
||||||
|
let deterministic_nonce sk_uri buf =
|
||||||
|
secret_key sk_uri >>=? fun sk ->
|
||||||
|
return (Signature.deterministic_nonce sk buf)
|
||||||
|
|
||||||
|
let deterministic_nonce_hash sk_uri buf =
|
||||||
|
secret_key sk_uri >>=? fun sk ->
|
||||||
|
return (Signature.deterministic_nonce_hash sk buf)
|
||||||
|
@ -23,9 +23,24 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
module Sign = struct
|
module type Authenticated_request = sig
|
||||||
|
type t = {
|
||||||
|
pkh: Signature.Public_key_hash.t ;
|
||||||
|
data: MBytes.t ;
|
||||||
|
signature: Signature.t option ;
|
||||||
|
}
|
||||||
|
val to_sign:
|
||||||
|
pkh: Signature.Public_key_hash.t ->
|
||||||
|
data: MBytes.t ->
|
||||||
|
MBytes.t
|
||||||
|
val encoding : t Data_encoding.t
|
||||||
|
end
|
||||||
|
|
||||||
module Request = struct
|
module type Tag = sig
|
||||||
|
val tag: int
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make_authenticated_request(T: Tag) : Authenticated_request = struct
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
pkh: Signature.Public_key_hash.t ;
|
pkh: Signature.Public_key_hash.t ;
|
||||||
@ -34,8 +49,11 @@ module Sign = struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
let to_sign ~pkh ~data =
|
let to_sign ~pkh ~data =
|
||||||
|
let tag = MBytes.make 1 '0' in
|
||||||
|
MBytes.set_int8 tag 0 T.tag;
|
||||||
MBytes.concat ""
|
MBytes.concat ""
|
||||||
[ MBytes.of_string "\x04" ;
|
[ MBytes.of_string "\x04" ;
|
||||||
|
tag;
|
||||||
Signature.Public_key_hash.to_bytes pkh ;
|
Signature.Public_key_hash.to_bytes pkh ;
|
||||||
data ]
|
data ]
|
||||||
|
|
||||||
@ -53,6 +71,10 @@ module Sign = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Sign = struct
|
||||||
|
|
||||||
|
module Request = Make_authenticated_request (struct let tag = 1 end)
|
||||||
|
|
||||||
module Response = struct
|
module Response = struct
|
||||||
|
|
||||||
type t = Signature.t
|
type t = Signature.t
|
||||||
@ -64,6 +86,37 @@ module Sign = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Deterministic_nonce = struct
|
||||||
|
|
||||||
|
module Request = Make_authenticated_request (struct let tag = 2 end)
|
||||||
|
|
||||||
|
module Response = struct
|
||||||
|
|
||||||
|
type t = MBytes.t
|
||||||
|
|
||||||
|
let encoding =
|
||||||
|
Data_encoding.(obj1 (req "deterministic_nonce" bytes))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Deterministic_nonce_hash = struct
|
||||||
|
|
||||||
|
module Request = Make_authenticated_request (struct let tag = 3 end)
|
||||||
|
|
||||||
|
module Response = struct
|
||||||
|
|
||||||
|
type t = MBytes.t
|
||||||
|
|
||||||
|
let encoding =
|
||||||
|
Data_encoding.(obj1 (req "deterministic_nonce_hash" bytes))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
module Public_key = struct
|
module Public_key = struct
|
||||||
|
|
||||||
module Request = struct
|
module Request = struct
|
||||||
@ -118,6 +171,8 @@ module Request = struct
|
|||||||
| Sign of Sign.Request.t
|
| Sign of Sign.Request.t
|
||||||
| Public_key of Public_key.Request.t
|
| Public_key of Public_key.Request.t
|
||||||
| Authorized_keys
|
| Authorized_keys
|
||||||
|
| Deterministic_nonce of Deterministic_nonce.Request.t
|
||||||
|
| Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t
|
||||||
|
|
||||||
let encoding =
|
let encoding =
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
@ -141,6 +196,20 @@ module Request = struct
|
|||||||
(obj1 (req "kind" (constant "authorized_keys")))
|
(obj1 (req "kind" (constant "authorized_keys")))
|
||||||
(function Authorized_keys -> Some () | _ -> None)
|
(function Authorized_keys -> Some () | _ -> None)
|
||||||
(fun () -> Authorized_keys) ;
|
(fun () -> Authorized_keys) ;
|
||||||
|
case (Tag 3)
|
||||||
|
~title:"Deterministic_nonce"
|
||||||
|
(merge_objs
|
||||||
|
(obj1 (req "kind" (constant "deterministic_nonce")))
|
||||||
|
Deterministic_nonce.Request.encoding)
|
||||||
|
(function Deterministic_nonce req -> Some ((), req) | _ -> None)
|
||||||
|
(fun ((), req) -> Deterministic_nonce req) ;
|
||||||
|
case (Tag 4)
|
||||||
|
~title:"Deterministic_nonce_hash"
|
||||||
|
(merge_objs
|
||||||
|
(obj1 (req "kind" (constant "deterministic_nonce_hash")))
|
||||||
|
Deterministic_nonce_hash.Request.encoding)
|
||||||
|
(function Deterministic_nonce_hash req -> Some ((), req) | _ -> None)
|
||||||
|
(fun ((), req) -> Deterministic_nonce_hash req) ;
|
||||||
]
|
]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -23,9 +23,7 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
module Sign : sig
|
module type Authenticated_request = sig
|
||||||
|
|
||||||
module Request : sig
|
|
||||||
type t = {
|
type t = {
|
||||||
pkh: Signature.Public_key_hash.t ;
|
pkh: Signature.Public_key_hash.t ;
|
||||||
data: MBytes.t ;
|
data: MBytes.t ;
|
||||||
@ -38,6 +36,10 @@ module Sign : sig
|
|||||||
val encoding : t Data_encoding.t
|
val encoding : t Data_encoding.t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Sign : sig
|
||||||
|
|
||||||
|
module Request : Authenticated_request
|
||||||
|
|
||||||
module Response : sig
|
module Response : sig
|
||||||
type t = Signature.t
|
type t = Signature.t
|
||||||
val encoding : t Data_encoding.t
|
val encoding : t Data_encoding.t
|
||||||
@ -45,6 +47,28 @@ module Sign : sig
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Deterministic_nonce : sig
|
||||||
|
|
||||||
|
module Request : Authenticated_request
|
||||||
|
|
||||||
|
module Response : sig
|
||||||
|
type t = MBytes.t
|
||||||
|
val encoding : t Data_encoding.t
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Deterministic_nonce_hash : sig
|
||||||
|
|
||||||
|
module Request : Authenticated_request
|
||||||
|
|
||||||
|
module Response : sig
|
||||||
|
type t = MBytes.t
|
||||||
|
val encoding : t Data_encoding.t
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
module Public_key : sig
|
module Public_key : sig
|
||||||
|
|
||||||
module Request : sig
|
module Request : sig
|
||||||
@ -70,12 +94,15 @@ module Authorized_keys : sig
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module Request : sig
|
module Request : sig
|
||||||
|
|
||||||
type t =
|
type t =
|
||||||
| Sign of Sign.Request.t
|
| Sign of Sign.Request.t
|
||||||
| Public_key of Public_key.Request.t
|
| Public_key of Public_key.Request.t
|
||||||
| Authorized_keys
|
| Authorized_keys
|
||||||
|
| Deterministic_nonce of Deterministic_nonce.Request.t
|
||||||
|
| Deterministic_nonce_hash of Deterministic_nonce_hash.Request.t
|
||||||
val encoding : t Data_encoding.t
|
val encoding : t Data_encoding.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
let sign =
|
|
||||||
let query =
|
let query =
|
||||||
let open RPC_query in
|
let open RPC_query in
|
||||||
query (fun signature -> signature)
|
query (fun signature -> signature)
|
||||||
@ -33,7 +33,9 @@ let sign =
|
|||||||
of the public key hash and message concatenated, by one \
|
of the public key hash and message concatenated, by one \
|
||||||
of the keys authorized by the signer."
|
of the keys authorized by the signer."
|
||||||
"authentication" Signature.rpc_arg (fun signature -> signature)
|
"authentication" Signature.rpc_arg (fun signature -> signature)
|
||||||
|> seal in
|
|> seal
|
||||||
|
|
||||||
|
let sign =
|
||||||
RPC_service.post_service
|
RPC_service.post_service
|
||||||
~description: "Sign a piece of data with a given remote key"
|
~description: "Sign a piece of data with a given remote key"
|
||||||
~query
|
~query
|
||||||
@ -41,6 +43,22 @@ let sign =
|
|||||||
~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
|
~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
|
||||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||||
|
|
||||||
|
let deterministic_nonce =
|
||||||
|
RPC_service.post_service
|
||||||
|
~description: "Obtain some random data generated deterministically from some piece of data with a given remote key"
|
||||||
|
~query
|
||||||
|
~input: Data_encoding.bytes
|
||||||
|
~output: Data_encoding.(obj1 (req "deterministic_nonce" bytes))
|
||||||
|
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||||
|
|
||||||
|
let deterministic_nonce_hash =
|
||||||
|
RPC_service.post_service
|
||||||
|
~description: "Obtain the hash of some random data generated deterministically from some piece of data with a given remote key"
|
||||||
|
~query
|
||||||
|
~input: Data_encoding.bytes
|
||||||
|
~output: Data_encoding.(obj1 (req "deterministic_nonce_hash" bytes))
|
||||||
|
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||||
|
|
||||||
let public_key =
|
let public_key =
|
||||||
RPC_service.get_service
|
RPC_service.get_service
|
||||||
~description: "Retrieve the public key of a given remote key"
|
~description: "Retrieve the public key of a given remote key"
|
||||||
|
@ -27,6 +27,14 @@ val sign :
|
|||||||
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||||
Signature.t option, MBytes.t, Signature.t) RPC_service.t
|
Signature.t option, MBytes.t, Signature.t) RPC_service.t
|
||||||
|
|
||||||
|
val deterministic_nonce :
|
||||||
|
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||||
|
Signature.t option, MBytes.t, MBytes.t) RPC_service.t
|
||||||
|
|
||||||
|
val deterministic_nonce_hash :
|
||||||
|
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||||
|
Signature.t option, MBytes.t, MBytes.t) RPC_service.t
|
||||||
|
|
||||||
val public_key :
|
val public_key :
|
||||||
([ `GET ], unit, unit * Signature.Public_key_hash.t,
|
([ `GET ], unit, unit * Signature.Public_key_hash.t,
|
||||||
unit, unit, Signature.Public_key.t) RPC_service.t
|
unit, unit, Signature.Public_key.t) RPC_service.t
|
||||||
|
Loading…
Reference in New Issue
Block a user