Alpha/Vote: docstrings and one renaming

This patchs adds documentation to the code.
It does not change the semantics.
parent 91fa2d7f
......@@ -25,8 +25,8 @@
open Alpha_context
let () = ()
(** Returns the proposal submitted by the most delegates.
Returns None in case of a tie or if there are no proposals. *)
let select_winning_proposal proposals =
let merge proposal vote winners =
match winners with
......@@ -43,6 +43,14 @@ let select_winning_proposal proposals =
| Some ([proposal], _) -> Some proposal
| Some _ -> None (* in case of a tie, lets do nothing. *)
(** A proposal is approved if it has supermajority and the participation reaches
the current quorum.
Supermajority means the yays are more 8/10 of casted votes.
The participation is the ratio of all received votes, including passes, with
respect to the number of possible votes. The quorum starts at 80% and at
each vote is updated using the last expected quorum and the current
participation with the following weights:
newQ = oldQ * 8/10 + participation * 2/10 *)
let check_approval_and_update_quorum ctxt =
Vote.get_ballots ctxt >>=? fun ballots ->
Vote.listing_size ctxt >>=? fun maximum_vote ->
......@@ -64,7 +72,11 @@ let check_approval_and_update_quorum ctxt =
Compare.Int32.(actual_quorum >= expected_quorum
&& ballots.yay >= supermajority))
let start_new_voting_cycle ctxt =
(** Implements the state machine of the amendment procedure.
Note that [freeze_listings], that computes the vote weight of each delegate,
is run at the beginning of each voting period.
*)
let start_new_voting_period ctxt =
Vote.get_current_period_kind ctxt >>=? function
| Proposal -> begin
Vote.get_proposals ctxt >>=? fun proposals ->
......@@ -252,9 +264,9 @@ let last_of_a_voting_period ctxt l =
Compare.Int32.(Int32.succ l.Level.voting_period_position =
Constants.blocks_per_voting_period ctxt )
let may_start_new_voting_cycle ctxt =
let may_start_new_voting_period ctxt =
let level = Level.current ctxt in
if last_of_a_voting_period ctxt level then
start_new_voting_cycle ctxt
start_new_voting_period ctxt
else
return ctxt
......@@ -23,9 +23,35 @@
(* *)
(*****************************************************************************)
(**
Only delegates with at least one roll take part in the amendment procedure.
It works as follows:
- Proposal period: delegates can submit protocol amendment proposals using
the proposal operation. At the end of a proposal period, the proposal with
most supporters is selected and we move to a testing_vote period.
If there are no proposals, or a tie between proposals, a new proposal
period starts.
- Testing_vote period: delegates can cast votes to test or not the winning
proposal using the ballot operation.
At the end of a testing_vote period if participation reaches the quorum
and the proposal has a supermajority in favor, we proceed to a testing
period. Otherwise we go back to a proposal period.
In any case, if there is enough participation the quorum is updated.
- Testing period: a test chain is forked for the lengh of the period.
At the end of a testing period we move to a promotion_vote period.
- Promotion_vote period: delegates can cast votes to promote or not the
tested proposal using the ballot operation.
At the end of a promotion_vote period if participation reaches the quorum
and the tested proposal has a supermajority in favor, it is activated as
the new protocol. Otherwise we go back to a proposal period.
In any case, if there is enough participation the quorum is updated.
*)
open Alpha_context
val may_start_new_voting_cycle:
(** If at the end of a voting period, moves to the next one following
the state machine of the amendment procedure. *)
val may_start_new_voting_period:
context -> context tzresult Lwt.t
type error +=
......@@ -34,6 +60,9 @@ type error +=
| Too_many_proposals
| Empty_proposal
(** Records a list of proposals for a delegate.
@raise Unexpected_proposal if [ctxt] is not in a proposal period.
@raise Unauthorized_proposal if [delegate] is not in the listing. *)
val record_proposals:
context ->
public_key_hash -> Protocol_hash.t list ->
......
......@@ -1020,7 +1020,7 @@ let finalize_application ctxt protocol_data delegate =
(* end of cycle *)
may_snapshot_roll ctxt >>=? fun ctxt ->
may_start_new_cycle ctxt >>=? fun (ctxt, balance_updates, deactivated) ->
Amendment.may_start_new_voting_cycle ctxt >>=? fun ctxt ->
Amendment.may_start_new_voting_period ctxt >>=? fun ctxt ->
let cycle = (Level.current ctxt).cycle in
let balance_updates =
Delegate.(cleanup_balance_updates
......
......@@ -234,32 +234,38 @@ module Vote : sig
with type value = Voting_period_repr.kind
and type t := Raw_context.t
(** Expected quorum, in centile of percentage *)
module Current_quorum : Single_data_storage
with type value = int32 (* in centile of percentage *)
with type value = int32
and type t := Raw_context.t
module Current_proposal : Single_data_storage
with type value = Protocol_hash.t
and type t := Raw_context.t
(** Sum of all rolls of all delegates. *)
module Listings_size : Single_data_storage
with type value = int32 (* total number of rolls in the listing. *)
with type value = int32
and type t := Raw_context.t
(** Contains all delegates with their assigned number of rolls. *)
module Listings : Indexed_data_storage
with type key = Signature.Public_key_hash.t
and type value = int32 (* number of rolls for the key. *)
and type value = int32
and type t := Raw_context.t
(** Set of protocol proposal with corresponding proposer delegate *)
module Proposals : Data_set_storage
with type elt = Protocol_hash.t * Signature.Public_key_hash.t
and type t := Raw_context.t
(** Keeps for each delegate the number of proposed protocols *)
module Proposals_count : Indexed_data_storage
with type key = Signature.Public_key_hash.t
and type value = int
and type t := Raw_context.t
(** Contains for each delegate its ballot *)
module Ballots : Indexed_data_storage
with type key = Signature.Public_key_hash.t
and type value = Vote_repr.ballot
......
......@@ -50,11 +50,11 @@ module type Single_data_storage = sig
val get_option: context -> value option tzresult Lwt.t
(** Allocates the storage bucket and initializes it ; returns a
{!Storage_error Missing_key} if the bucket exists *)
{!Storage_error Existing_key} if the bucket exists *)
val init: context -> value -> Raw_context.t tzresult Lwt.t
(** Updates the content of the bucket ; returns a {!Storage_Error
Existing_key} if the value does not exists *)
Missing_key} if the value does not exists *)
val set: context -> value -> Raw_context.t tzresult Lwt.t
(** Allocates the data and initializes it with a value ; just
......
......@@ -23,11 +23,8 @@
(* *)
(*****************************************************************************)
(* a protocol change proposal *)
type proposal = Protocol_hash.t
(* votes can be for, against or neutral.
Neutral serves to count towards a quorum *)
type ballot = Yay | Nay | Pass
let ballot_encoding =
......
......@@ -23,7 +23,10 @@
(* *)
(*****************************************************************************)
(** a protocol change proposal *)
type proposal = Protocol_hash.t
(** votes can be for, against or neutral.
Neutral serves to count towards a quorum *)
type ballot = Yay | Nay | Pass
val ballot_encoding: ballot Data_encoding.t
......@@ -132,6 +132,7 @@ let init_current_proposal = Storage.Vote.Current_proposal.init
let clear_current_proposal = Storage.Vote.Current_proposal.delete
let init ctxt =
(* quorum is in centile of a percentage *)
Storage.Vote.Current_quorum.init ctxt 80_00l >>=? fun ctxt ->
Storage.Vote.Current_period_kind.init ctxt Proposal >>=? fun ctxt ->
return ctxt
......@@ -23,7 +23,9 @@
(* *)
(*****************************************************************************)
(** Records a proposal per delegate *)
(** Manages all the voting related storage in Storage.Vote. *)
(** Records a protocol proposal with the delegate that proposed it. *)
val record_proposal:
Raw_context.t -> Protocol_hash.t -> Signature.Public_key_hash.t ->
Raw_context.t tzresult Lwt.t
......@@ -32,11 +34,13 @@ val recorded_proposal_count_for_delegate:
Raw_context.t -> Signature.Public_key_hash.t ->
int tzresult Lwt.t
(** Computes for each proposal how many delegates proposed it. *)
val get_proposals:
Raw_context.t -> int32 Protocol_hash.Map.t tzresult Lwt.t
val clear_proposals: Raw_context.t -> Raw_context.t Lwt.t
(** Counts of the votes *)
type ballots = {
yay: int32 ;
nay: int32 ;
......@@ -46,9 +50,14 @@ type ballots = {
val ballots_encoding : ballots Data_encoding.t
val has_recorded_ballot : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t
(** Records a vote for a delegate, returns a {!Storage_error Existing_key} if
the vote was already registered *)
val record_ballot:
Raw_context.t -> Signature.Public_key_hash.t -> Vote_repr.ballot ->
Raw_context.t tzresult Lwt.t
(** Computes the sum of the current ballots weighted by stake. *)
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
......@@ -56,10 +65,15 @@ val clear_ballots: Raw_context.t -> Raw_context.t Lwt.t
val listings_encoding : (Signature.Public_key_hash.t * int32) list Data_encoding.t
(** Populates [!Storage.Vote.Listings] using the currently existing rolls and
sets Listings_size. Delegates without rolls are not included in the listing. *)
val freeze_listings: Raw_context.t -> Raw_context.t tzresult Lwt.t
val clear_listings: Raw_context.t -> Raw_context.t tzresult Lwt.t
(** Returns the sum of all rolls of all delegates. *)
val listing_size: Raw_context.t -> int32 tzresult Lwt.t
(** Verifies the presence of a delegate in the listing. *)
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
......@@ -78,4 +92,5 @@ val init_current_proposal:
Raw_context.t -> Protocol_hash.t -> Raw_context.t tzresult Lwt.t
val clear_current_proposal: Raw_context.t -> Raw_context.t tzresult Lwt.t
(** Sets the initial quorum to 80% and period kind to proposal. *)
val init: Raw_context.t -> Raw_context.t tzresult Lwt.t
......@@ -23,6 +23,9 @@
(* *)
(*****************************************************************************)
(** A voting period can be of 4 kinds and is uniquely identified as a counter
since the root. *)
type t
type voting_period = t
val encoding: voting_period Data_encoding.t
......@@ -37,9 +40,9 @@ val root: voting_period
val succ: voting_period -> voting_period
type kind =
| Proposal
| Testing_vote
| Testing
| Promotion_vote
| Proposal (** protocols can be proposed *)
| Testing_vote (** a proposal can be voted *)
| Testing (** winning proposal is forked on a testnet *)
| Promotion_vote (** activation can be voted *)
val kind_encoding: kind Data_encoding.t
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment