diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 9aa77288cc26608aeebaf852a413d87e21dc2fee..2e9f1602afd6ff803e4b707acb366475f24b2e7a 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -90,7 +90,11 @@ let handle_post_store_preimage dac_plugin cctxt dac_sk_uris page_store data in let* signature, witnesses = - Signature_manager.sign_root_hash dac_plugin cctxt dac_sk_uris root_hash + Signature_manager.Legacy.sign_root_hash + dac_plugin + cctxt + dac_sk_uris + root_hash in let raw_root_hash = Dac_plugin.hash_to_raw root_hash in let*! external_message = @@ -134,10 +138,10 @@ let handle_monitor_root_hashes hash_streamer = let* () = Event.(emit handle_new_subscription_to_hash_streamer ()) in Tezos_rpc.Answer.return_stream {next; shutdown} -let handle_get_certificate dac_plugin ctx raw_root_hash = +let handle_get_certificate dac_plugin node_store raw_root_hash = let open Lwt_result_syntax in let*? root_hash = Dac_plugin.raw_to_hash dac_plugin raw_root_hash in - let node_store = Node_context.get_node_store ctx Store_sigs.Read_only in + let+ value_opt = Store.Certificate_store.find node_store root_hash in Option.map (fun Store.{aggregate_signature; witnesses} -> @@ -192,34 +196,19 @@ let register_monitor_root_hashes hash_streamer dir = Monitor_services.S.root_hashes (fun () () () -> handle_monitor_root_hashes hash_streamer) -let register_put_dac_member_signature ctx cctxt = - add_service - Tezos_rpc.Directory.register0 - RPC_services.put_dac_member_signature - (fun () dac_member_signature -> - Signature_manager.Coordinator.handle_put_dac_member_signature - ctx - cctxt - dac_member_signature) - -let register_get_certificate ctx dac_plugin = +let register_get_certificate node_store dac_plugin = add_service Tezos_rpc.Directory.register1 RPC_services.get_certificate - (fun root_hash () () -> handle_get_certificate dac_plugin ctx root_hash) + (fun root_hash () () -> + handle_get_certificate dac_plugin node_store root_hash) -let register_get_missing_page ctx dac_plugin = - match Node_context.mode ctx with - | Legacy _ | Observer _ -> - add_service - Tezos_rpc.Directory.register1 - RPC_services.get_missing_page - (fun root_hash () () -> - let open Lwt_result_syntax in - let page_store = Node_context.get_page_store ctx in - let*? cctxt = Node_context.get_coordinator_client ctx in - handle_get_missing_page cctxt page_store dac_plugin root_hash) - | Coordinator _ | Committee_member _ -> Fun.id +let register_get_missing_page dac_plugin page_store cctxt = + add_service + Tezos_rpc.Directory.register1 + RPC_services.get_missing_page + (fun root_hash () () -> + handle_get_missing_page cctxt page_store dac_plugin root_hash) module Coordinator = struct let handle_post_preimage dac_plugin page_store hash_streamer payload = @@ -238,7 +227,7 @@ module Coordinator = struct in return @@ Dac_plugin.hash_to_raw root_hash - let handle_monitor_certificate dac_plugin ro_store certificate_streamers + let handle_monitor_certificate dac_plugin ro_node_store certificate_streamers raw_root_hash committee_members = let open Lwt_result_syntax in let*? stream, stopper = @@ -255,7 +244,7 @@ module Coordinator = struct a certificate is returned even in the case that no updates to the certificate happen for a long time. *) let*! current_certificate_store_value_res = - Store.Certificate_store.find ro_store root_hash + Store.Certificate_store.find ro_node_store root_hash in match current_certificate_store_value_res with | Ok current_certificate_store_value -> @@ -291,8 +280,8 @@ module Coordinator = struct return (next, shutdown) | Error e -> fail e - let register_monitor_certificate dac_plugin ro_store certificate_streamers - committee_members dir = + let register_monitor_certificate dac_plugin ro_node_store + certificate_streamers committee_members dir = Tezos_rpc.Directory.gen_register dir Monitor_services.S.certificate @@ -301,7 +290,7 @@ module Coordinator = struct let*! handler = handle_monitor_certificate dac_plugin - ro_store + ro_node_store certificate_streamers root_hash committee_members @@ -310,77 +299,98 @@ module Coordinator = struct | Ok (next, shutdown) -> Tezos_rpc.Answer.return_stream {next; shutdown} | Error e -> Tezos_rpc.Answer.fail e) - let register_coordinator_post_preimage dac_plugin hash_streamer page_store = + let register_post_preimage dac_plugin hash_streamer page_store = add_service Tezos_rpc.Directory.register0 RPC_services.Coordinator.post_preimage (fun () payload -> handle_post_preimage dac_plugin page_store hash_streamer payload) - let dynamic_rpc_dir dac_plugin (node_ctxt : Node_context.t) = - let modal_node_ctxt = - match Node_context.mode node_ctxt with - | Coordinator modal_node_ctxt -> modal_node_ctxt - (* We only pass [Node_context.t] values whose mode is [Coordinator _] to - this function. *) - | _ -> assert false - in + let register_put_dac_member_signature ctx dac_plugin rw_node_store page_store + cctxt = + add_service + Tezos_rpc.Directory.register0 + RPC_services.put_dac_member_signature + (fun () dac_member_signature -> + Signature_manager.Coordinator.handle_put_dac_member_signature + ctx + dac_plugin + rw_node_store + page_store + cctxt + dac_member_signature) + let dynamic_rpc_dir dac_plugin rw_store page_store cctxt coordinator_node_ctxt + = let hash_streamer = - modal_node_ctxt.Node_context.Coordinator.hash_streamer + coordinator_node_ctxt.Node_context.Coordinator.hash_streamer in let public_keys_opt = - Node_context.Coordinator.public_keys_opt modal_node_ctxt + Node_context.Coordinator.public_keys_opt coordinator_node_ctxt in - let page_store = Node_context.get_page_store node_ctxt in - let cctxt = Node_context.get_tezos_node_cctxt node_ctxt in - let certificate_streamers = modal_node_ctxt.certificate_streamers in - let ro_store = Node_context.get_node_store node_ctxt Store_sigs.Read_only in - let committee_members = modal_node_ctxt.committee_members in + let certificate_streamers = coordinator_node_ctxt.certificate_streamers in + let committee_members = coordinator_node_ctxt.committee_members in Tezos_rpc.Directory.empty - |> register_coordinator_post_preimage dac_plugin hash_streamer page_store + |> register_post_preimage dac_plugin hash_streamer page_store |> register_get_verify_signature dac_plugin public_keys_opt |> register_get_preimage dac_plugin page_store |> register_monitor_root_hashes hash_streamer |> register_monitor_certificate dac_plugin - ro_store + rw_store certificate_streamers committee_members - |> register_put_dac_member_signature node_ctxt cctxt - |> register_get_certificate node_ctxt dac_plugin + |> register_put_dac_member_signature + coordinator_node_ctxt + dac_plugin + rw_store + page_store + cctxt + |> register_get_certificate rw_store dac_plugin end module Committee_member = struct - let dynamic_rpc_dir dac_plugin (node_ctxt : Node_context.t) = - let page_store = Node_context.get_page_store node_ctxt in + let dynamic_rpc_dir dac_plugin page_store = Tezos_rpc.Directory.empty |> register_get_preimage dac_plugin page_store end module Observer = struct - let dynamic_rpc_dir dac_plugin (node_ctxt : Node_context.t) = - let page_store = Node_context.get_page_store node_ctxt in + let dynamic_rpc_dir dac_plugin coordinator_cctxt page_store = Tezos_rpc.Directory.empty |> register_get_preimage dac_plugin page_store - |> register_get_missing_page node_ctxt dac_plugin + |> register_get_missing_page dac_plugin page_store coordinator_cctxt end module Legacy = struct - let dynamic_rpc_dir dac_plugin (node_ctxt : Node_context.t) = - let modal_node_ctxt = - match Node_context.mode node_ctxt with - | Legacy modal_node_ctxt -> modal_node_ctxt - (* We only pass [Node_context.t] values whose mode is [Coordinator _] to - this function. *) - | _ -> assert false + let register_put_dac_member_signature ctx dac_plugin rw_node_store page_store + cctxt = + add_service + Tezos_rpc.Directory.register0 + RPC_services.put_dac_member_signature + (fun () dac_member_signature -> + Signature_manager.Legacy.handle_put_dac_member_signature + ctx + dac_plugin + rw_node_store + page_store + cctxt + dac_member_signature) + + let dynamic_rpc_dir dac_plugin rw_store page_store cctxt legacy_node_ctxt = + let hash_streamer = legacy_node_ctxt.Node_context.Legacy.hash_streamer in + let public_keys_opt = + Node_context.Legacy.public_keys_opt legacy_node_ctxt in - let hash_streamer = modal_node_ctxt.Node_context.Legacy.hash_streamer in - let public_keys_opt = Node_context.Legacy.public_keys_opt modal_node_ctxt in let secret_key_uris_opt = - Node_context.Legacy.secret_key_uris_opt modal_node_ctxt + Node_context.Legacy.secret_key_uris_opt legacy_node_ctxt + in + let register_get_missing_page = + match legacy_node_ctxt.coordinator_cctxt with + | None -> fun dir -> dir + | Some cctxt -> + fun dir -> + dir |> register_get_missing_page dac_plugin page_store cctxt in - let page_store = Node_context.get_page_store node_ctxt in - let cctxt = Node_context.get_tezos_node_cctxt node_ctxt in Tezos_rpc.Directory.empty |> register_post_store_preimage dac_plugin @@ -391,20 +401,41 @@ module Legacy = struct |> register_get_verify_signature dac_plugin public_keys_opt |> register_get_preimage dac_plugin page_store |> register_monitor_root_hashes hash_streamer - |> register_put_dac_member_signature node_ctxt cctxt - |> register_get_certificate node_ctxt dac_plugin - |> register_get_missing_page node_ctxt dac_plugin + |> register_put_dac_member_signature + legacy_node_ctxt + dac_plugin + rw_store + page_store + cctxt + |> register_get_certificate rw_store dac_plugin + |> register_get_missing_page end let start ~rpc_address ~rpc_port node_ctxt = let open Lwt_syntax in + let rw_store = Node_context.get_node_store node_ctxt Store_sigs.Read_write in + let page_store = Node_context.get_page_store node_ctxt in + let cctxt = Node_context.get_tezos_node_cctxt node_ctxt in let register_dynamic_rpc dac_plugin = - match Node_context.mode node_ctxt with - | Coordinator _ -> Coordinator.dynamic_rpc_dir dac_plugin node_ctxt - | Committee_member _ -> - Committee_member.dynamic_rpc_dir dac_plugin node_ctxt - | Observer _ -> Observer.dynamic_rpc_dir dac_plugin node_ctxt - | Legacy _ -> Legacy.dynamic_rpc_dir dac_plugin node_ctxt + match Node_context.get_mode node_ctxt with + | Coordinator coordinator_node_ctxt -> + Coordinator.dynamic_rpc_dir + dac_plugin + rw_store + page_store + cctxt + coordinator_node_ctxt + | Committee_member _committee_member_node_ctxt -> + Committee_member.dynamic_rpc_dir dac_plugin page_store + | Observer {coordinator_cctxt; _} -> + Observer.dynamic_rpc_dir dac_plugin coordinator_cctxt page_store + | Legacy legacy_node_ctxt -> + Legacy.dynamic_rpc_dir + dac_plugin + rw_store + page_store + cctxt + legacy_node_ctxt in let dir = Tezos_rpc.Directory.register_dynamic_directory diff --git a/src/lib_dac_node/configuration.ml b/src/lib_dac_node/configuration.ml index 6c034400a5f96c87740ab91958de3d92e3409a96..5712cd8c7c4b855e2727a854b33fca4a38e12c0d 100644 --- a/src/lib_dac_node/configuration.ml +++ b/src/lib_dac_node/configuration.ml @@ -68,6 +68,8 @@ module Coordinator = struct (list Tezos_crypto.Aggregate_signature.Public_key_hash.encoding)))) let committee_members_addresses t = t.committee_members_addresses + + let name = "Coordinator" end module Committee_member = struct @@ -93,6 +95,8 @@ module Committee_member = struct (req "address" Tezos_crypto.Aggregate_signature.Public_key_hash.encoding))) + + let name = "Committee_member" end module Observer = struct @@ -111,6 +115,8 @@ module Observer = struct (obj2 (req "coordinator_rpc_address" string) (req "coordinator_rpc_port" uint16))) + + let name = "Observer" end module Legacy = struct @@ -180,6 +186,8 @@ module Legacy = struct (opt "committee_member_address_opt" Tezos_crypto.Aggregate_signature.Public_key_hash.encoding))) + + let name = "Legacy" end type mode = @@ -222,6 +230,13 @@ type t = { DAC. *) } +let mode_name t = + match t.mode with + | Coordinator _ -> Coordinator.name + | Committee_member _ -> Committee_member.name + | Observer _ -> Observer.name + | Legacy _ -> Legacy.name + let make ~data_dir ~reveal_data_dir rpc_address rpc_port mode = {data_dir; reveal_data_dir; rpc_address; rpc_port; mode} @@ -240,26 +255,26 @@ let mode_encoding = union [ case - ~title:"Coordinator" - (Tag (0, "coordinator")) + ~title:Coordinator.name + (Tag (0, Coordinator.name)) Coordinator.encoding (function Coordinator t -> Some t | _ -> None) (fun t -> Coordinator t); case - ~title:"Committee_member" - (Tag (1, "committee_member")) + ~title:Committee_member.name + (Tag (1, Committee_member.name)) Committee_member.encoding (function Committee_member t -> Some t | _ -> None) (fun t -> Committee_member t); case - ~title:"Observer" - (Tag (2, "observer")) + ~title:Observer.name + (Tag (2, Observer.name)) Observer.encoding (function Observer t -> Some t | _ -> None) (fun t -> Observer t); case - ~title:"Legacy" - (Tag (3, "legacy")) + ~title:Legacy.name + (Tag (3, Legacy.name)) Legacy.encoding (function Legacy t -> Some t | _ -> None) (fun t -> Legacy t); diff --git a/src/lib_dac_node/configuration.mli b/src/lib_dac_node/configuration.mli index 172b9fe44f8c01234c6b8918eb26734094a88fd8..abd344f29e2c2facf99183ad0482249ca72a66a4 100644 --- a/src/lib_dac_node/configuration.mli +++ b/src/lib_dac_node/configuration.mli @@ -108,6 +108,10 @@ type t = private { DAC. *) } +(** [mode_name t] returns a string representation of the operating mode + for the configuration [t]. *) +val mode_name : t -> string + (** [make_coordinator threshold dac_members_addresses] creates a new coordinator configuration mode using the given [threshold] and [dac_members_addresses]. *) diff --git a/src/lib_dac_node/daemon.ml b/src/lib_dac_node/daemon.ml index 1589861fd3e4afeb95674c8ec02da3c4b5558107..8ba9dc68a44f4317afca9192e1a7f419fe6971d1 100644 --- a/src/lib_dac_node/daemon.ml +++ b/src/lib_dac_node/daemon.ml @@ -53,38 +53,6 @@ let daemonize handlers = return_unit) |> lwt_map_error (List.fold_left (fun acc errs -> errs @ acc) []) -let get_all_committee_members_keys pkhs ~threshold wallet_cctxt = - let open Lwt_result_syntax in - let* wallet_accounts = - List.map_es - (fun pkh -> - Wallet_account.Legacy.of_committee_member_address pkh wallet_cctxt) - pkhs - in - let*! valid_wallet_accounts = - List.filter_s - (fun Wallet_account.Legacy.{public_key_hash; secret_key_uri_opt; _} -> - if Option.is_some secret_key_uri_opt then Lwt.return true - else - let*! () = - Event.(emit committee_member_cannot_sign public_key_hash) - in - Lwt.return false) - wallet_accounts - in - let recovered_keys = List.length valid_wallet_accounts in - let*! () = - (* We emit a warning if the threshold of dac accounts needed to sign a - root page hash is not reached. We also emit a warning for each DAC - account whose secret key URI was not recovered. - We do not stop the dac node at this stage. - *) - if recovered_keys < threshold then - Event.(emit dac_threshold_not_reached (recovered_keys, threshold)) - else Event.(emit dac_is_ready) () - in - return wallet_accounts - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/3605 Improve general architecture, handle L1 disconnection etc *) @@ -96,6 +64,8 @@ let run ~data_dir cctxt = config) = Configuration.load ~data_dir in + let operating_mode_string = Configuration.mode_name config in + let*! () = Event.(emit operating_mode operating_mode_string) in let* () = Page_store.ensure_reveal_data_dir_exists reveal_data_dir in let* ctxt = Node_context.init config cctxt in (* TODO: https://gitlab.com/tezos/tezos/-/issues/4725 diff --git a/src/lib_dac_node/event.ml b/src/lib_dac_node/event.ml index 081d816c84c4cd7b35d14988642903fa69f9c719..943ef6006b1920f027e41ff020d407a60dfaaa54 100644 --- a/src/lib_dac_node/event.ml +++ b/src/lib_dac_node/event.ml @@ -52,6 +52,14 @@ let store_is_ready = ~level:Notice () +let operating_mode = + declare_1 + ~section + ~name:"dac_node_running_mode" + ~msg:"The DAC node is running in mode {mode}" + ~level:Notice + ("mode", Data_encoding.string) + let rpc_server_is_ready = declare_2 ~section diff --git a/src/lib_dac_node/handler.ml b/src/lib_dac_node/handler.ml index 05e3869e2bec0485407cabb0893ecec6252141a0..472fea25d6afc0d9fde87192f92224ba898a41a9 100644 --- a/src/lib_dac_node/handler.ml +++ b/src/lib_dac_node/handler.ml @@ -362,7 +362,7 @@ let handlers node_ctxt = let*? plugin = Node_context.get_dac_plugin node_ctxt in let page_store = Node_context.get_page_store node_ctxt in let wallet_cctxt = Node_context.get_tezos_node_cctxt node_ctxt in - match Node_context.mode node_ctxt with + match Node_context.get_mode node_ctxt with | Coordinator _ -> return [new_head node_ctxt] | Committee_member ctxt -> return diff --git a/src/lib_dac_node/node_context.ml b/src/lib_dac_node/node_context.ml index 47416656e5b0b23f10adaa8b6f111d5c28dee9ce..15a2306d9c6d5bd4d83667f39cbb9355c0375e2c 100644 --- a/src/lib_dac_node/node_context.ml +++ b/src/lib_dac_node/node_context.ml @@ -63,6 +63,11 @@ module Coordinator = struct List.map (fun Wallet_account.Coordinator.{public_key_opt; _} -> public_key_opt) t.committee_members + + let committee_members t = + List.map + (fun Wallet_account.Coordinator.{public_key_hash; _} -> public_key_hash) + t.committee_members end module Committee_member = struct @@ -196,6 +201,11 @@ module Legacy = struct List.map (fun Wallet_account.Legacy.{secret_key_uri_opt; _} -> secret_key_uri_opt) t.committee_members + + let committee_members t = + List.map + (fun Wallet_account.Legacy.{public_key_hash; _} -> public_key_hash) + t.committee_members end type mode = @@ -251,7 +261,7 @@ let init config cctxt = mode; } -let mode node_ctxt = node_ctxt.mode +let get_mode node_ctxt = node_ctxt.mode let set_ready ctxt dac_plugin = match ctxt.status with @@ -263,10 +273,7 @@ let set_ready ctxt dac_plugin = ctxt.status <- Ready {dac_plugin} | Ready _ -> raise Status_already_ready -type error += - | Node_not_ready - | Invalid_operation_for_mode of {mode : string; operation : string} - | Coordinator_client_not_defined_in_config +type error += Node_not_ready let () = register_error_kind @@ -280,39 +287,7 @@ let () = "DAC node is starting. It's not ready to respond to RPCs.") Data_encoding.(unit) (function Node_not_ready -> Some () | _ -> None) - (fun () -> Node_not_ready) ; - register_error_kind - `Permanent - ~id:"dac_unexpected_mode" - ~title:"Invalid operation for the current mode of Dac node." - ~description: - "An operation was called that it not supported by the current Dac node." - ~pp:(fun ppf (mode, operation) -> - Format.fprintf - ppf - "An operation was called that it not supported by the current Dac \ - node. Mode: %s; Unsupported_operation: %s" - mode - operation) - Data_encoding.( - obj2 (req "mode" (string' Plain)) (req "operation" (string' Plain))) - (function - | Invalid_operation_for_mode {mode; operation} -> Some (mode, operation) - | _ -> None) - (fun (mode, operation) -> Invalid_operation_for_mode {mode; operation}) ; - register_error_kind - `Permanent - ~id:"dac_coordinator_client_not_defined_in_config" - ~title:"Coordinator client was not defined in config." - ~description: - "Coordinator client configuration was expected but not defined." - ~pp:(fun ppf () -> - Format.fprintf - ppf - "Coordinator client configuration was expected but not defined.") - Data_encoding.unit - (function Coordinator_client_not_defined_in_config -> Some () | _ -> None) - (fun () -> Coordinator_client_not_defined_in_config) + (fun () -> Node_not_ready) let get_ready ctxt = let open Result_syntax in @@ -337,31 +312,3 @@ let get_node_store (type a) ctxt (access_mode : a Store_sigs.mode) : match access_mode with | Store_sigs.Read_only -> Store.Irmin_store.readonly ctxt.node_store | Store_sigs.Read_write -> ctxt.node_store - -let get_committee_members ctxt = - let open Result_syntax in - match ctxt.mode with - | Legacy legacy -> - Ok - (List.map - (fun Wallet_account.Legacy.{public_key_hash; _} -> public_key_hash) - legacy.committee_members) - | Coordinator coordinator -> - Ok - ((List.map (fun Wallet_account.Coordinator.{public_key_hash; _} -> - public_key_hash)) - coordinator.committee_members) - | Observer _ -> - tzfail - @@ Invalid_operation_for_mode - {mode = "observer"; operation = "get_committee_members"} - | Committee_member _ -> - tzfail - @@ Invalid_operation_for_mode - {mode = "dac_member"; operation = "get_committee_members"} - -let get_coordinator_client ctxt = - match ctxt.mode with - | Observer observer_ctxt -> Ok observer_ctxt.coordinator_cctxt - | Legacy {coordinator_cctxt = Some cctxt; _} -> Ok cctxt - | _ -> Result_syntax.tzfail Coordinator_client_not_defined_in_config diff --git a/src/lib_dac_node/node_context.mli b/src/lib_dac_node/node_context.mli index 132354bfaebc2944ddd9922608015b8cc91efadd..bcd6a697c66da7cdbe641c6c6f10fa7ede099fbf 100644 --- a/src/lib_dac_node/node_context.mli +++ b/src/lib_dac_node/node_context.mli @@ -50,6 +50,9 @@ module Coordinator : sig data availability committee of [t]. *) val public_keys_opt : t -> Tezos_crypto.Aggregate_signature.public_key option list + + val committee_members : + t -> Tezos_crypto.Aggregate_signature.public_key_hash list end (** [Committee_member] defines a partial [Node_context.t] that is available @@ -111,6 +114,9 @@ module Legacy : sig (** [secret_key_uris_opt] return the list of optional secret key URIs of the committee members of [t]. *) val secret_key_uris_opt : t -> Client_keys.aggregate_sk_uri option list + + val committee_members : + t -> Tezos_crypto.Aggregate_signature.public_key_hash list end (** Operating mode specific fraction of a [Node_context.t] *) @@ -156,9 +162,9 @@ val get_ready : t -> ready_ctxt tzresult (** [get_status ctxt] returns the dac node status. *) val get_status : t -> status -(** [mode node_ctxt] returns the operating mode specific fraction of a +(** [get_mode node_ctxt] returns the operating mode specific fraction of a [Node_context.t]. *) -val mode : t -> mode +val get_mode : t -> mode (** [get_tezos_node_cctxt ctxt] returns the Tezos node's client context. *) val get_tezos_node_cctxt : t -> Client_context.full @@ -174,13 +180,3 @@ val get_page_store : t -> Page_store.Filesystem.t (** [get_node_store ctxt access_mode] returns the [Store.Irmin_store.t] with [access_mode] used by Dac components. *) val get_node_store : t -> 'a Store_sigs.mode -> 'a Store.Irmin_store.t - -(** [get_committee_members ctxt] returns the Dac committee public key hashes from - [Configuration.Legacy.dac_members_addresses] or - [Configuration.Coordinator.dac_members_addresses] *) -val get_committee_members : - t -> Tezos_crypto.Aggregate_signature.public_key_hash list tzresult - -(** [get_coordinator_client ctx] returns the Coordinator client if it - is available. *) -val get_coordinator_client : t -> Dac_node_client.cctxt tzresult diff --git a/src/lib_dac_node/signature_manager.ml b/src/lib_dac_node/signature_manager.ml index 5fef6f9aa1d2d5224b70738cf6cc774f20ab90c8..8b35e08a52993d3f5f454927db5abfc07257b83d 100644 --- a/src/lib_dac_node/signature_manager.ml +++ b/src/lib_dac_node/signature_manager.ml @@ -24,10 +24,17 @@ (* *) (*****************************************************************************) +module Aggregate_signature = Tezos_crypto.Aggregate_signature + type error += | Cannot_convert_root_page_hash_to_bytes of string | Cannot_compute_aggregate_signature of string | Public_key_for_witness_not_available of int * string + | Public_key_is_non_committee_member of Aggregate_signature.public_key_hash + | Signature_verification_failed of + (Aggregate_signature.public_key * Aggregate_signature.t * string) + | Public_key_for_committee_member_not_available of + Aggregate_signature.public_key_hash let () = register_error_kind @@ -63,14 +70,16 @@ let () = `Permanent ~id:"public_key_of_witness_not_available" ~title: - "Public key of witness dac member not available for verifying signature" + "Public key of witness committee member not available for verifying \ + signature" ~description: - "Public key of witness dac member not available for verifying signature" + "Public key of witness committee member not available for verifying \ + signature" ~pp:(fun ppf (witness_index, b58_hash) -> Format.fprintf ppf - "Public key of dac member %d not available for verifying signature of \ - root page hash %s" + "Public key of committee member %d not available for verifying \ + signature of root page hash %s" witness_index b58_hash) Data_encoding.( @@ -78,7 +87,76 @@ let () = (function | Public_key_for_witness_not_available (index, hash) -> Some (index, hash) | _ -> None) - (fun (index, hash) -> Public_key_for_witness_not_available (index, hash)) + (fun (index, hash) -> Public_key_for_witness_not_available (index, hash)) ; + register_error_kind + `Permanent + ~id:"Public_key_is_non_committee_member" + ~title:"Public key hash is not a committee member" + ~description: + "Public key hash is not associated with any committee member registered \ + with this Dac coordinator." + ~pp:(fun ppf committee_member_pkh -> + Format.fprintf + ppf + "Expected public key to be an active committee member but was not: %s" + (Tezos_crypto.Aggregate_signature.Public_key_hash.to_short_b58check + committee_member_pkh)) + Data_encoding.( + obj1 + (req + "public_key_hash" + Tezos_crypto.Aggregate_signature.Public_key_hash.encoding)) + (function + | Public_key_is_non_committee_member committee_member_pkh -> + Some committee_member_pkh + | _ -> None) + (fun committee_member_pkh -> + Public_key_is_non_committee_member committee_member_pkh) ; + register_error_kind + `Permanent + ~id:"signature_verification_failed" + ~title:"Signature verification failed" + ~description:"Signature verification failed." + ~pp:(fun ppf (pk, signature, root_hash) -> + let pk = Aggregate_signature.Public_key.to_short_b58check pk in + let signature = Aggregate_signature.to_short_b58check signature in + Format.fprintf + ppf + "Could not verify signature \"%s\" given public key \"%s\" and \ + root_hash \"%s\": Signature verification failed." + pk + signature + root_hash) + Data_encoding.( + obj3 + (req "public_key" Aggregate_signature.Public_key.encoding) + (req "signature" Aggregate_signature.encoding) + (req "root_hash" (string' Plain))) + (function + | Signature_verification_failed (pk, signature, root_hash) -> + Some (pk, signature, root_hash) + | _ -> None) + (function + | pk, signature, root_hash -> + Signature_verification_failed (pk, signature, root_hash)) ; + register_error_kind + `Permanent + ~id:"public_key_of_committee_member_not_available" + ~title:"Public key of committee member not available." + ~description:"Public key of committee member not available." + ~pp:(fun ppf b58_hash -> + Format.fprintf + ppf + "Public key of committee member %s not available." + b58_hash) + Data_encoding.(obj1 (req "hash" (string' Plain))) + (function + | Public_key_for_committee_member_not_available hash -> + Some (Aggregate_signature.Public_key_hash.to_b58check hash) + | _ -> None) + (fun hash -> + Public_key_for_committee_member_not_available + (Aggregate_signature.Public_key_hash.of_b58check_exn hash)) let bind_es (f : 'a -> 'b option tzresult Lwt.t) v_opt = let open Lwt_result_syntax in @@ -117,28 +195,6 @@ let compute_signatures_with_witnesses rev_indexed_signatures = ([], Z.zero) rev_indexed_signatures -let sign_root_hash ((module Plugin) : Dac_plugin.t) cctxt dac_sk_uris root_hash - = - let open Lwt_result_syntax in - let bytes_to_sign = - Data_encoding.Binary.to_bytes_opt Plugin.encoding root_hash - in - let root_hash = Plugin.to_hex root_hash in - match bytes_to_sign with - | None -> tzfail @@ Cannot_convert_root_page_hash_to_bytes root_hash - | Some bytes_to_sign -> ( - let* rev_indexed_signatures = - rev_collect_indexed_signatures cctxt dac_sk_uris bytes_to_sign - in - let* signatures, witnesses = - compute_signatures_with_witnesses rev_indexed_signatures - in - match - Tezos_crypto.Aggregate_signature.aggregate_signature_opt signatures - with - | None -> tzfail @@ Cannot_compute_aggregate_signature root_hash - | Some signature -> return @@ (signature, witnesses)) - let verify dac_plugin ~public_keys_opt root_page_hash signature witnesses = let open Lwt_result_syntax in let ((module Plugin) : Dac_plugin.t) = dac_plugin in @@ -168,281 +224,218 @@ let verify dac_plugin ~public_keys_opt root_page_hash signature witnesses = return @@ Tezos_crypto.Aggregate_signature.aggregate_check pk_msg_list signature -module Coordinator = struct - module Aggregate_signature = Tezos_crypto.Aggregate_signature - - type error += - | Public_key_is_non_dac_member of Aggregate_signature.public_key_hash - | Signature_verification_failed of - (Aggregate_signature.public_key * Aggregate_signature.t * string) - | Public_key_for_dac_member_not_available of - Aggregate_signature.public_key_hash - | Unknown_root_hash of string +let verify_signature ((module Plugin) : Dac_plugin.t) pk signature root_hash = + let root_hash_bytes = Dac_plugin.hash_to_bytes root_hash in + fail_unless + (Aggregate_signature.check pk signature root_hash_bytes) + (Signature_verification_failed (pk, signature, Plugin.to_hex root_hash)) - let () = - register_error_kind - `Permanent - ~id:"Public_key_is_non_dac_member" - ~title:"Public key hash is not a valid dac member" - ~description: - "Public key hash is not associated with any Dac member registered with \ - this Dac coordinator." - ~pp:(fun ppf dac_member_pkh -> - Format.fprintf - ppf - "Expected public key to be an active Dac committee member but was \ - not: %s" - (Tezos_crypto.Aggregate_signature.Public_key_hash.to_short_b58check - dac_member_pkh)) - Data_encoding.( - obj1 - (req - "public_key_hash" - Tezos_crypto.Aggregate_signature.Public_key_hash.encoding)) - (function - | Public_key_is_non_dac_member dac_member_pkh -> Some dac_member_pkh - | _ -> None) - (fun dac_member_pkh -> Public_key_is_non_dac_member dac_member_pkh) ; - register_error_kind - `Permanent - ~id:"signature_verification_failed" - ~title:"Signature verification failed" - ~description:"Signature verification failed." - ~pp:(fun ppf (pk, signature, root_hash) -> - let pk = Aggregate_signature.Public_key.to_short_b58check pk in - let signature = Aggregate_signature.to_short_b58check signature in - Format.fprintf - ppf - "Could not verify signature \"%s\" given public key \"%s\" and \ - root_hash \"%s\": Signature verification failed." - pk - signature - root_hash) - Data_encoding.( - obj3 - (req "public_key" Aggregate_signature.Public_key.encoding) - (req "signature" Aggregate_signature.encoding) - (req "root_hash" (string' Plain))) - (function - | Signature_verification_failed (pk, signature, root_hash) -> - Some (pk, signature, root_hash) - | _ -> None) - (function - | pk, signature, root_hash -> - Signature_verification_failed (pk, signature, root_hash)) ; - register_error_kind - `Permanent - ~id:"public_key_of_dac_member_not_available" - ~title:"Public key of dac member not available." - ~description:"Public key of dac member not available." - ~pp:(fun ppf b58_hash -> - Format.fprintf ppf "Public key of dac member %s not available." b58_hash) - Data_encoding.(obj1 (req "hash" (string' Plain))) - (function - | Public_key_for_dac_member_not_available hash -> - Some (Aggregate_signature.Public_key_hash.to_b58check hash) - | _ -> None) - (fun hash -> - Public_key_for_dac_member_not_available - (Aggregate_signature.Public_key_hash.of_b58check_exn hash)) ; - register_error_kind - `Permanent - ~id:"unknown_root_hash" - ~title:"No data associated to the provided root hash" - ~description:"There is no data in storage for this root hash" - ~pp:(fun ppf hash -> - Format.fprintf - ppf - "There is no data available for the root page hash %s" - hash) - Data_encoding.(obj1 (req "hash" (string' Plain))) - (function Unknown_root_hash hash -> Some hash | _ -> None) - (fun hash -> Unknown_root_hash hash) +let add_dac_member_signature dac_plugin signature_store + Signature_repr.{root_hash; signer_pkh; signature} = + let open Lwt_result_syntax in + let*? root_hash = Dac_plugin.raw_to_hash dac_plugin root_hash in + Store.Signature_store.add + signature_store + ~primary_key:root_hash + ~secondary_key:signer_pkh + signature - let verify_signature ((module Plugin) : Dac_plugin.t) pk signature root_hash = - let root_hash_bytes = Dac_plugin.hash_to_bytes root_hash in - fail_unless - (Aggregate_signature.check pk signature root_hash_bytes) - (Signature_verification_failed (pk, signature, Plugin.to_hex root_hash)) +let rev_find_indexed_signatures node_store dac_members_pkh root_hash = + let open Lwt_result_syntax in + List.rev_mapi_es + (fun index dac_member_pk -> + let+ (signature_opt : Aggregate_signature.t option) = + Store.Signature_store.find + node_store + ~primary_key:root_hash + ~secondary_key:dac_member_pk + in + Option.map (fun signature -> (index, signature)) signature_opt) + dac_members_pkh - let add_dac_member_signature dac_plugin signature_store - Signature_repr.{root_hash; signer_pkh; signature} = - let open Lwt_result_syntax in - let*? root_hash = Dac_plugin.raw_to_hash dac_plugin root_hash in - Store.Signature_store.add - signature_store - ~primary_key:root_hash - ~secondary_key:signer_pkh - signature +let update_aggregate_sig_store node_store dac_members_pk_opt root_hash = + let open Lwt_result_syntax in + let* rev_indexed_signature = + rev_find_indexed_signatures node_store dac_members_pk_opt root_hash + in + let* signatures, witnesses = + compute_signatures_with_witnesses rev_indexed_signature + in + let final_signature = + Tezos_crypto.Aggregate_signature.aggregate_signature_opt signatures + in + match final_signature with + | None -> + tzfail + @@ Cannot_compute_aggregate_signature + (Hex.show @@ Dac_plugin.hash_to_hex root_hash) + | Some aggregate_signature -> + let* () = + Store.Certificate_store.add + node_store + root_hash + Store.{aggregate_signature; witnesses} + in + return @@ (aggregate_signature, witnesses) - let rev_find_indexed_signatures node_store dac_members_pk root_hash = - let open Lwt_result_syntax in - List.rev_mapi_es - (fun index dac_member_pk -> - let+ (signature_opt : Aggregate_signature.t option) = - Store.Signature_store.find - node_store - ~primary_key:root_hash - ~secondary_key:dac_member_pk - in - Option.map (fun signature -> (index, signature)) signature_opt) - dac_members_pk +let check_dac_member_has_signed signature_store root_hash dac_member_pkh = + Store.Signature_store.mem + signature_store + ~primary_key:root_hash + ~secondary_key:dac_member_pkh - let update_aggregate_sig_store node_store dac_members_pk_opt root_hash = - let open Lwt_result_syntax in - let* rev_indexed_signature = - rev_find_indexed_signatures node_store dac_members_pk_opt root_hash - in - let* signatures, witnesses = - compute_signatures_with_witnesses rev_indexed_signature - in - match - Tezos_crypto.Aggregate_signature.aggregate_signature_opt signatures - with - | None -> - tzfail - @@ Cannot_compute_aggregate_signature - (Hex.show @@ Dac_plugin.hash_to_hex root_hash) - | Some aggregate_signature -> - let* () = - Store.Certificate_store.add - node_store - root_hash - Store.{aggregate_signature; witnesses} - in - return @@ (aggregate_signature, witnesses) +let check_is_dac_member dac_committee signer_pkh = + Option.is_some + @@ List.find + (fun pkh -> Aggregate_signature.Public_key_hash.equal signer_pkh pkh) + dac_committee - let check_dac_member_has_signed signature_store root_hash dac_member_pkh = - let open Lwt_result_syntax in - let* dac_member_has_signed = - Store.Signature_store.mem - signature_store - ~primary_key:root_hash - ~secondary_key:dac_member_pkh - in - return dac_member_has_signed +let check_coordinator_knows_root_hash dac_plugin page_store root_hash = + let open Lwt_result_syntax in + let ((module Plugin) : Dac_plugin.t) = dac_plugin in + let*! has_payload = + Page_store.Filesystem.mem (module Plugin) page_store root_hash + in + match has_payload with + | Error _ -> + tzfail + @@ Page_store.Cannot_read_page_from_page_storage (Plugin.to_hex root_hash) + (* Return an HTTP 404 error when hash provided in signature is unknown *) + | Ok false -> raise Not_found + | Ok true -> return () - let check_is_dac_member dac_committee signer_pkh = - Option.is_some - @@ List.find - (fun pkh -> Aggregate_signature.Public_key_hash.equal signer_pkh pkh) - dac_committee +let should_update_certificate dac_plugin cctxt ro_node_store committee_members + Signature_repr.{signer_pkh; root_hash; signature} = + let open Lwt_result_syntax in + let ((module Plugin) : Dac_plugin.t) = dac_plugin in + let*? root_hash = Dac_plugin.raw_to_hash dac_plugin root_hash in + let* () = + fail_unless + (check_is_dac_member committee_members signer_pkh) + (Public_key_is_non_committee_member signer_pkh) + in + let* pub_key_opt = Wallet_cctxt_helpers.get_public_key cctxt signer_pkh in + let* pub_key = + Option.fold_f + ~none:(fun () -> + tzfail (Public_key_for_committee_member_not_available signer_pkh)) + ~some:return + pub_key_opt + in + let* dac_member_has_signed = + check_dac_member_has_signed ro_node_store root_hash signer_pkh + in + if dac_member_has_signed then return false + else + let* () = verify_signature dac_plugin pub_key signature root_hash in + return true - let check_coordinator_knows_root_hash dac_plugin page_store raw_root_hash = - let open Lwt_result_syntax in - let ((module Plugin) : Dac_plugin.t) = dac_plugin in - let*? root_hash = Dac_plugin.raw_to_hash dac_plugin raw_root_hash in - let*! has_payload = - Page_store.Filesystem.mem (module Plugin) page_store root_hash +let stream_certificate_update dac_plugin committee_members + (Certificate_repr.{root_hash; _} as certificate) certificate_streamers = + let open Result_syntax in + let* () = + Certificate_streamers.push + dac_plugin + certificate_streamers + root_hash + certificate + in + if + Certificate_repr.all_committee_members_have_signed + committee_members + certificate + then + let _ = + Certificate_streamers.close dac_plugin certificate_streamers root_hash in - match has_payload with - | Error _ -> - tzfail - @@ Page_store.Cannot_read_page_from_page_storage - (Plugin.to_hex root_hash) - (* Return an HTTP 404 error when hash provided in signature is unknown *) - | Ok false -> raise Not_found - | Ok true -> return () + return () + else return () - let should_update_certificate dac_plugin cctxt ro_node_store committee_members - Signature_repr.{signer_pkh; root_hash; signature} = - let ((module Plugin) : Dac_plugin.t) = dac_plugin in - let open Lwt_result_syntax in - let*? root_hash = Dac_plugin.raw_to_hash dac_plugin root_hash in +let handle_put_dac_member_signature dac_plugin certificate_streamers_opt + rw_node_store page_store cctxt committee_members committee_member_signature + = + let open Lwt_result_syntax in + let ((module Plugin) : Dac_plugin.t) = dac_plugin in + let Signature_repr.{root_hash = raw_root_hash; _} = + committee_member_signature + in + let*? root_hash = Dac_plugin.raw_to_hash dac_plugin raw_root_hash in + let* () = check_coordinator_knows_root_hash dac_plugin page_store root_hash in + let* should_update_certificate = + should_update_certificate + dac_plugin + cctxt + rw_node_store + committee_members + committee_member_signature + in + if should_update_certificate then let* () = - fail_unless - (check_is_dac_member committee_members signer_pkh) - (Public_key_is_non_dac_member signer_pkh) + add_dac_member_signature + dac_plugin + rw_node_store + committee_member_signature in - let* pub_key_opt = Wallet_cctxt_helpers.get_public_key cctxt signer_pkh in - let* pub_key = - Option.fold_f - ~none:(fun () -> - tzfail (Public_key_for_dac_member_not_available signer_pkh)) - ~some:return - pub_key_opt + let* aggregate_signature, witnesses = + update_aggregate_sig_store rw_node_store committee_members root_hash in - let* dac_member_has_signed = - check_dac_member_has_signed ro_node_store root_hash signer_pkh + let*? () = + Option.iter_e + (stream_certificate_update + dac_plugin + committee_members + Certificate_repr. + {root_hash = raw_root_hash; aggregate_signature; witnesses}) + certificate_streamers_opt in - if dac_member_has_signed then return false - else - let* () = verify_signature dac_plugin pub_key signature root_hash in - return true + return () + else return () - let stream_certificate_update dac_plugin committee_members - (Certificate_repr.{root_hash; _} as certificate) certificate_streamers = - let open Result_syntax in - let* () = - Certificate_streamers.push - dac_plugin - certificate_streamers - root_hash - certificate - in - if - Certificate_repr.all_committee_members_have_signed - committee_members - certificate - then - let _ = - Certificate_streamers.close dac_plugin certificate_streamers root_hash - in - return () - else return () +module Coordinator = struct + let handle_put_dac_member_signature ctx dac_plugin rw_node_store page_store + cctxt dac_member_signature = + let committee_members = Node_context.Coordinator.committee_members ctx in + handle_put_dac_member_signature + dac_plugin + (Some ctx.certificate_streamers) + rw_node_store + page_store + cctxt + committee_members + dac_member_signature +end - let handle_put_dac_member_signature ctx cctxt committee_member_signature = +module Legacy = struct + let sign_root_hash ((module P) : Dac_plugin.t) cctxt dac_sk_uris root_hash = let open Lwt_result_syntax in - let* certificate_streamers_opt = - match Node_context.mode ctx with - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5292 - Make type non optional when Legacy mode has been removed. *) - | Node_context.Coordinator {certificate_streamers; _} -> - return @@ Some certificate_streamers - | Legacy _ -> return None - | _ -> - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5370 - This line will never be executed as - [handle_put_dac_member_signature] is only invoked when the - DAC node is running in either coordinator or legacy mode. - *) - failwith "Operation not supported for operating mode" - in - let*? dac_plugin = Node_context.get_dac_plugin ctx in - let page_store = Node_context.get_page_store ctx in - let*? committee_members = Node_context.get_committee_members ctx in - let rw_node_store = Node_context.get_node_store ctx Store_sigs.Read_write in - let Signature_repr.{root_hash; _} = committee_member_signature in - let* () = - check_coordinator_knows_root_hash dac_plugin page_store root_hash + let bytes_to_sign = + Data_encoding.Binary.to_bytes_opt P.encoding root_hash in - let* should_update_certificate = - should_update_certificate - dac_plugin - cctxt - rw_node_store - committee_members - committee_member_signature - in - if should_update_certificate then - let* () = - add_dac_member_signature - dac_plugin - rw_node_store - committee_member_signature - in - let*? root_hash' = Dac_plugin.raw_to_hash dac_plugin root_hash in - let* aggregate_signature, witnesses = - update_aggregate_sig_store rw_node_store committee_members root_hash' - in - let*? () = - Option.iter_e - (stream_certificate_update - dac_plugin - committee_members - Certificate_repr.{root_hash; aggregate_signature; witnesses}) - certificate_streamers_opt - in - return () - else return () + let root_hash = P.to_hex root_hash in + match bytes_to_sign with + | None -> tzfail @@ Cannot_convert_root_page_hash_to_bytes root_hash + | Some bytes_to_sign -> ( + let* rev_indexed_signatures = + rev_collect_indexed_signatures cctxt dac_sk_uris bytes_to_sign + in + let* signatures, witnesses = + compute_signatures_with_witnesses rev_indexed_signatures + in + match + Tezos_crypto.Aggregate_signature.aggregate_signature_opt signatures + with + | None -> tzfail @@ Cannot_compute_aggregate_signature root_hash + | Some signature -> return @@ (signature, witnesses)) + + let handle_put_dac_member_signature ctx dac_plugin rw_node_store page_store + cctxt dac_member_signature = + let committee_members = Node_context.Legacy.committee_members ctx in + handle_put_dac_member_signature + dac_plugin + None + rw_node_store + page_store + cctxt + committee_members + dac_member_signature end diff --git a/src/lib_dac_node/signature_manager.mli b/src/lib_dac_node/signature_manager.mli index 5e9288cc2c11715843d06be1108a6228ff5429c6..9afa9f5bb76a3ace976d480fb4ab135ebb2e123b 100644 --- a/src/lib_dac_node/signature_manager.mli +++ b/src/lib_dac_node/signature_manager.mli @@ -29,16 +29,14 @@ type error += | Cannot_convert_root_page_hash_to_bytes of string | Cannot_compute_aggregate_signature of string | Public_key_for_witness_not_available of int * string - -(* [sign_root_hash dac_pliugin cctx dac_sk_uris_opt root_hash] is legacy function that - returns an aggregate signature over [root_hash] and a bitmap of witnesses where - empty elements of [dac_sk_uris_opt] are 0 and non-empty elements are 1. *) -val sign_root_hash : - Dac_plugin.t -> - #Client_context.wallet -> - Client_keys.aggregate_sk_uri option trace -> - Dac_plugin.hash -> - (Tezos_crypto.Aggregate_signature.signature * Z.t, tztrace) result Lwt.t + | Public_key_is_non_committee_member of + Tezos_crypto.Aggregate_signature.public_key_hash + | Signature_verification_failed of + (Tezos_crypto.Aggregate_signature.public_key + * Tezos_crypto.Aggregate_signature.t + * string) + | Public_key_for_committee_member_not_available of + Tezos_crypto.Aggregate_signature.public_key_hash (** [verify dac_plugin public_keys_opt root_hash aggregate_signature witnesses] verifies the [aggregate_signature] signed by the witnessed dac members. The witnessed @@ -55,30 +53,54 @@ val verify : (** Module that exposes signature operations necsesary when running in [Configuration.Coordinator] mode.*) module Coordinator : sig - type error += - | Public_key_is_non_dac_member of - Tezos_crypto.Aggregate_signature.public_key_hash - | Signature_verification_failed of - (Tezos_crypto.Aggregate_signature.public_key - * Tezos_crypto.Aggregate_signature.t - * string) - | Public_key_for_dac_member_not_available of - Tezos_crypto.Aggregate_signature.public_key_hash - | Unknown_root_hash of string + (** [handle_put_dac_member_signature ctx dac_plugin ro_store rw_store page_store + cctxt dac_member_signature] does the following procedure: + 1. Checks that the [root_hash] provided inside [Signature_repr.t] is known. Fails if unknown + 2. Checks that the [dac_member_signature.signer_pkh] is currently a Dac member. + 3. Checks that the dac member has not yet signed. If already signed, then noop + and return. + 4. Otherwise: + 1. Verify the signature against the root hash and signer's public key. + 2. Add signature to [Signature_store] + 3. Update the aggregate signature in [Aggregate_signature_store] + *) + val handle_put_dac_member_signature : + Node_context.Coordinator.t -> + Dac_plugin.t -> + Store_sigs.rw Store.Irmin_store.t -> + Page_store.Filesystem.t -> + #Client_context.wallet -> + Signature_repr.t -> + unit tzresult Lwt.t +end + +module Legacy : sig + (* [sign_root_hash dac_pliugin cctx dac_sk_uris_opt root_hash] is legacy function that + returns an aggregate signature over [root_hash] and a bitmap of witnesses where + empty elements of [dac_sk_uris_opt] are 0 and non-empty elements are 1. *) + val sign_root_hash : + Dac_plugin.t -> + #Client_context.wallet -> + Client_keys.aggregate_sk_uri option trace -> + Dac_plugin.hash -> + (Tezos_crypto.Aggregate_signature.signature * Z.t, tztrace) result Lwt.t - (** [handle_put_dac_member_signature ctxt cctxt dac_members_pkh dac_member_signature] - does the following procedure: + (** [handle_put_dac_member_signature ctx dac_plugin ro_store rw_store page_store + cctxt dac_member_signature] does the following procedure: 1. Checks that the [root_hash] provided inside [Signature_repr.t] is known. Fails if unknown - 1. Checks that the [dac_member_signature.signer_pkh] is currently a Dac member. - 2. Checks that the dac member has not yet signed. If already signed, then noop + 2. Checks that the [dac_member_signature.signer_pkh] is currently a Dac member. + 3. Checks that the dac member has not yet signed. If already signed, then noop and return. - 3. Otherwise: + 4. Otherwise: 1. Verify the signature against the root hash and signer's public key. 2. Add signature to [Signature_store] 3. Update the aggregate signature in [Aggregate_signature_store] *) val handle_put_dac_member_signature : - Node_context.t -> + Node_context.Legacy.t -> + Dac_plugin.t -> + Store_sigs.rw Store.Irmin_store.t -> + Page_store.Filesystem.t -> #Client_context.wallet -> Signature_repr.t -> unit tzresult Lwt.t