From f1614414cc96e6597d33ce0ebacda22918f93d85 Mon Sep 17 00:00:00 2001 From: Marco Stronati Date: Fri, 16 Nov 2018 15:07:08 +0100 Subject: [PATCH] Alpha/Vote: add RPCs to read voting state Co-authored-by: Jun FURUSE Co-authored-by: Marco Stronati --- .../lib_protocol/src/TEZOS_PROTOCOL | 1 + .../lib_protocol/src/alpha_context.mli | 6 + .../lib_protocol/src/alpha_services.ml | 4 +- .../lib_protocol/src/alpha_services.mli | 1 + .../lib_protocol/src/vote_storage.ml | 18 +++ .../lib_protocol/src/vote_storage.mli | 7 + .../lib_protocol/src/voting_services.ml | 138 ++++++++++++++++++ .../lib_protocol/src/voting_services.mli | 49 +++++++ 8 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 src/proto_alpha/lib_protocol/src/voting_services.ml create mode 100644 src/proto_alpha/lib_protocol/src/voting_services.mli diff --git a/src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL index f096ccd80..227ece362 100644 --- a/src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL @@ -73,6 +73,7 @@ "Contract_services", "Delegate_services", "Helpers_services", + "Voting_services", "Alpha_services", "Main" diff --git a/src/proto_alpha/lib_protocol/src/alpha_context.mli b/src/proto_alpha/lib_protocol/src/alpha_context.mli index 87bd553ce..8ae23b416 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_context.mli @@ -736,12 +736,15 @@ module Vote : sig context -> int32 Protocol_hash.Map.t Lwt.t val clear_proposals: context -> context Lwt.t + val listings_encoding : (Signature.Public_key_hash.t * int32) list Data_encoding.t val freeze_listings: context -> context tzresult Lwt.t val clear_listings: context -> context tzresult Lwt.t val listing_size: context -> int32 tzresult Lwt.t val in_listings: context -> public_key_hash -> bool Lwt.t + val get_listings : context -> (public_key_hash * int32) list Lwt.t type ballot = Yay | Nay | Pass + val ballot_encoding : ballot Data_encoding.t type ballots = { yay: int32 ; @@ -749,9 +752,12 @@ module Vote : sig pass: int32 ; } + val ballots_encoding : ballots Data_encoding.t + val record_ballot: context -> public_key_hash -> ballot -> context Lwt.t val get_ballots: context -> ballots tzresult Lwt.t + val get_ballot_list: context -> (Signature.Public_key_hash.t * ballot) list Lwt.t val clear_ballots: context -> context Lwt.t val get_current_period_kind: diff --git a/src/proto_alpha/lib_protocol/src/alpha_services.ml b/src/proto_alpha/lib_protocol/src/alpha_services.ml index 18871bfcc..5194db531 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_services.ml +++ b/src/proto_alpha/lib_protocol/src/alpha_services.ml @@ -116,10 +116,12 @@ module Delegate = Delegate_services module Helpers = Helpers_services module Forge = Helpers_services.Forge module Parse = Helpers_services.Parse +module Voting = Voting_services let register () = Contract.register () ; Constants.register () ; Delegate.register () ; Helpers.register () ; - Nonce.register () + Nonce.register () ; + Voting.register () diff --git a/src/proto_alpha/lib_protocol/src/alpha_services.mli b/src/proto_alpha/lib_protocol/src/alpha_services.mli index 48ed928ef..f6e4a6b25 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_services.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_services.mli @@ -50,5 +50,6 @@ module Delegate = Delegate_services module Helpers = Helpers_services module Forge = Helpers_services.Forge module Parse = Helpers_services.Parse +module Voting = Voting_services val register: unit -> unit diff --git a/src/proto_alpha/lib_protocol/src/vote_storage.ml b/src/proto_alpha/lib_protocol/src/vote_storage.ml index 01ede5e10..3655f762b 100644 --- a/src/proto_alpha/lib_protocol/src/vote_storage.ml +++ b/src/proto_alpha/lib_protocol/src/vote_storage.ml @@ -45,6 +45,16 @@ type ballots = { pass: int32 ; } +let ballots_encoding = + let open Data_encoding in + conv + (fun { yay ; nay ; pass } -> ( yay , nay , pass )) + (fun ( yay , nay , pass ) -> { yay ; nay ; pass }) + @@ obj3 + (req "yay" int32) + (req "nay" int32) + (req "pass" int32) + let record_ballot = Storage.Vote.Ballots.init_set let get_ballots ctxt = @@ -61,8 +71,15 @@ let get_ballots ctxt = end) ~init:(ok { yay = 0l ; nay = 0l; pass = 0l }) +let get_ballot_list = Storage.Vote.Ballots.bindings + let clear_ballots = Storage.Vote.Ballots.clear +let listings_encoding = + Data_encoding.(list (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "rolls" int32))) + let freeze_listings ctxt = Roll_storage.fold ctxt (ctxt, 0l) ~f:(fun _roll delegate (ctxt, total) -> @@ -81,6 +98,7 @@ let freeze_listings ctxt = let listing_size = Storage.Vote.Listings_size.get let in_listings = Storage.Vote.Listings.mem +let get_listings = Storage.Vote.Listings.bindings let clear_listings ctxt = Storage.Vote.Listings.clear ctxt >>= fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/src/vote_storage.mli b/src/proto_alpha/lib_protocol/src/vote_storage.mli index 2346678da..e01d3635f 100644 --- a/src/proto_alpha/lib_protocol/src/vote_storage.mli +++ b/src/proto_alpha/lib_protocol/src/vote_storage.mli @@ -38,18 +38,25 @@ type ballots = { pass: int32 ; } +val ballots_encoding : ballots Data_encoding.t + val record_ballot: Raw_context.t -> Signature.Public_key_hash.t -> Vote_repr.ballot -> Raw_context.t Lwt.t val get_ballots: Raw_context.t -> ballots tzresult Lwt.t +val get_ballot_list : + Raw_context.t -> (Signature.Public_key_hash.t * Vote_repr.ballot) list Lwt.t val clear_ballots: Raw_context.t -> Raw_context.t Lwt.t +val listings_encoding : (Signature.Public_key_hash.t * int32) list Data_encoding.t + val freeze_listings: Raw_context.t -> Raw_context.t tzresult Lwt.t val clear_listings: Raw_context.t -> Raw_context.t tzresult Lwt.t val listing_size: Raw_context.t -> int32 tzresult Lwt.t val in_listings: Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t +val get_listings : Raw_context.t -> (Signature.Public_key_hash.t * int32) list Lwt.t val get_current_quorum: Raw_context.t -> int32 tzresult Lwt.t val set_current_quorum: Raw_context.t -> int32 -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/src/voting_services.ml b/src/proto_alpha/lib_protocol/src/voting_services.ml new file mode 100644 index 000000000..26c93ca4b --- /dev/null +++ b/src/proto_alpha/lib_protocol/src/voting_services.ml @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +module S = struct + + let path = RPC_path.(open_root / "votes") + + let ballots = + RPC_service.get_service + ~description:"Sum of ballots casted so far during a voting period." + ~query: RPC_query.empty + ~output: Vote.ballots_encoding + RPC_path.(path / "ballots") + + let ballot_list = + RPC_service.get_service + ~description:"Ballots casted so far during a voting period." + ~query: RPC_query.empty + ~output: Data_encoding.(list (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "ballot" Vote.ballot_encoding))) + RPC_path.(path / "ballot_list") + + let current_period_kind = + RPC_service.get_service + ~description:"Current period kind." + ~query: RPC_query.empty + ~output: Voting_period.kind_encoding + RPC_path.(path / "current_period_kind") + + let current_quorum = + RPC_service.get_service + ~description:"Current expected quorum." + ~query: RPC_query.empty + ~output: Data_encoding.int32 + RPC_path.(path / "current_quorum") + + let listings = + RPC_service.get_service + ~description:"List of delegates with their voting weight, in number of rolls." + ~query: RPC_query.empty + ~output: Vote.listings_encoding + RPC_path.(path / "listings") + + let proposals = + RPC_service.get_service + ~description:"List of proposals with number of supporters." + ~query: RPC_query.empty + ~output: (Protocol_hash.Map.encoding Data_encoding.int32) + RPC_path.(path / "proposals") + + let current_proposal = + RPC_service.get_service + ~description:"Current proposal under evaluation." + ~query: RPC_query.empty + ~output: (Data_encoding.option Protocol_hash.encoding) + RPC_path.(path / "current_proposal") +end + +let register () = + let open Services_registration in + + register0 S.ballots begin fun ctxt () () -> + Vote.get_ballots ctxt + end; + + register0 S.ballot_list begin fun ctxt () () -> + Vote.get_ballot_list ctxt >|= ok + end; + + register0 S.current_period_kind begin fun ctxt () () -> + Vote.get_current_period_kind ctxt + end; + + register0 S.current_quorum begin fun ctxt () () -> + Vote.get_current_quorum ctxt + end; + + register0 S.proposals begin fun ctxt () () -> + Vote.get_proposals ctxt >|= ok + end; + + register0 S.listings begin fun ctxt () () -> + Vote.get_listings ctxt >|= ok + end; + + register0 S.current_proposal begin fun ctxt () () -> + (* this would be better implemented using get_option in get_current_proposal *) + Vote.get_current_proposal ctxt >>= function + | Ok p -> return (Some p) + | Error [Raw_context.Storage_error (Missing_key _)] -> return None + | (Error _ as e) -> Lwt.return e + end + +let ballots ctxt block = + RPC_context.make_call0 S.ballots ctxt block () () + +let ballot_list ctxt block = + RPC_context.make_call0 S.ballot_list ctxt block () () + +let current_period_kind ctxt block = + RPC_context.make_call0 S.current_period_kind ctxt block () () + +let current_quorum ctxt block = + RPC_context.make_call0 S.current_quorum ctxt block () () + +let listings ctxt block = + RPC_context.make_call0 S.listings ctxt block () () + +let proposals ctxt block = + RPC_context.make_call0 S.proposals ctxt block () () + +let current_proposal ctxt block = + RPC_context.make_call0 S.current_proposal ctxt block () () diff --git a/src/proto_alpha/lib_protocol/src/voting_services.mli b/src/proto_alpha/lib_protocol/src/voting_services.mli new file mode 100644 index 000000000..0cb4599d7 --- /dev/null +++ b/src/proto_alpha/lib_protocol/src/voting_services.mli @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val ballots : + 'a #RPC_context.simple -> 'a -> Vote.ballots shell_tzresult Lwt.t + +val ballot_list : + 'a #RPC_context.simple -> 'a -> (Signature.Public_key_hash.t * Vote.ballot) list shell_tzresult Lwt.t + +val current_period_kind : + 'a #RPC_context.simple -> 'a -> Voting_period.kind shell_tzresult Lwt.t + +val current_quorum : + 'a #RPC_context.simple -> 'a -> Int32.t shell_tzresult Lwt.t + +val listings : + 'a #RPC_context.simple -> 'a -> (Signature.Public_key_hash.t * int32) list shell_tzresult Lwt.t + +val proposals : + 'a #RPC_context.simple -> 'a -> Int32.t Protocol_hash.Map.t shell_tzresult Lwt.t + +val current_proposal : + 'a #RPC_context.simple -> 'a -> Protocol_hash.t option shell_tzresult Lwt.t + +val register : unit -> unit