diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 82587be1620a8..83cd74a0bee8a 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -14,22 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! # Council System Module +//! # Council Module //! //! -//! Council system: Handles the voting in and maintenance of council members. -//! //! ## Overview //! -//! The Council system module provides functionality for different voting systems, including: +//! The Council system module provides functionality for different voting systems to handle the voting in and maintenance of council members, including: //! //! * Council Motions //! * Council Seats //! * Council Voting //! -//! To use it in your runtime, you need to implement the council [`Trait`](./trait.Trait.html). -//! -//! The supported dispatchable functions are documented in the [`Call`](./enum.Call.html) enum. +//! - [`council::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) //! //! ### Terminology //! @@ -39,121 +37,60 @@ //! * **Councillor** A councillor is a countable stakeholder. They may vote on a council proposal during the voting period if they did not create the proposal. //! * **Council motion:** A mechanism used enact an outer `Call` dispatch (of type `Proposal`) from a council origin. //! * **Council motion vote:** Allows an arbitrary number of councillors (other than the councillor that proposed the motion) to vote and initiate a call. -//! * **Council origin:** The council origin is the Council (not Root) and contains the council motion mechanism. It has different mechanics to other origins. -//! * **Council proposal validity prerequisites:** A council proposal is valid when: -//! * Submitted by a councillor. -//! * Not a duplicate proposal. -//! * Not vetoed. -//! * Council term does not expire before the proposals' voting period has lapsed. +//! * **Council origin:** The council origin is the council (not root) and contains the council motion mechanism. It has different mechanics to other origins. +//! * **Council proposal validity prerequisites:** A council proposal is valid when it is submitted by a councillor, is not a duplicate proposal, has not been vetoed, and when the council term does not expire before the proposals' voting period has lapsed. //! * **Council proposal creation storage** A council proposal after being deemed valid is stored as follows: //! * Proposals' storage vector is updated with a tuple containing the proposal's hash and the expiry block number of its voting period. //! * Proposals' hash is mapped to the proposals' value in storage using `ProposalOf`. -//! * Proposals' hash is mapped to a vector of account ids that have voted the proposal in storage using `ProposalVoters`. Initially the account ID of the councillor that created the proposal is added to the vector. +//! * Proposals' hash is mapped to a vector of account ids that have voted the proposal in storage using `ProposalVoters`. Initially the account id of the councillor that created the proposal is added to the vector. //! * Councillor's vote storage tuple `CouncilVoteOf` is updated with a mapping between the proposal's hash and the councillor's account id. Initially the councillor that created the proposal is added with a vote of yay. -//! * **Council proposal postponement** Councillors that abstain from voting may postpone a council proposal from being approved or disapproved. Note: Postponing is equivalent to a **Council proposal veto** since the veto only lasts for the cooldown period. +//! * **Council proposal postponement** Councillors that abstain from voting may postpone a council proposal from being approved or disapproved. Note: Postponing is equivalent to a **council proposal veto** since the veto only lasts for the cooldown period. //! //! #### Council Proposal Voting //! //! * **Council proposal vote storage** A council proposal vote that occurs after council proposal creation is stored as follows: -//! * `ProposalVoters` storage vector that contains account IDs that have voted for the proposal's hash is updated with the Councillor's new vote. -//! * Councillor's vote storage tuple `CouncilVoteOf` is updated with a mapping between a tuple containing the proposal's hash and the councillor's account id, and the Councillor's new vote. -//! * `Voting` storage mapping is updated with the Councillor's vote. -//! * Note that `Voting` maps the proposal's hash to a tuple containing the corresponding proposal's index, vote threshold, and vectors of both yay and nay voter account IDs. -//! * **Council proposal voting rules** -//! * Duplicate votes from the same councillor are ignored. -//! * Councillors may swap their vote from yay to nay and vice versa. -//! * **Council proposal vote threshold** -//! * A council proposal that is created with a threshold level of one is voted upon and approved by the councillor that created it, and then executed. -//! * A council proposal with a threshold level of more than one is added to the `Voting` storage mapping. -//! * **Council proposal voting veto rules** -//! * A councillor may veto a proposal if its stored in the `ProposalVoters` mapping on condition that they have not vetoed it previously. -//! * Once a councillor vetoes a council proposal they cannot propose the proposal again until after a cooling off period that's measured in blocks. -//! * **Council proposal voting veto** -//! * If a councillors veto is valid then their veto is stored in `VetoedProposal` amongst other councillors that have vetoed the proposal, which maps the proposal's hash to a tuple comprising of the block number when the veto expires, and the account id of the vetoer. -//! * Vetoed proposals are removed from various storage locations, including the `Proposals` storage vector, the `ProposalsOf` storage mapping, the `ProposalVoters` storage mapping, and the `CouncilVoteOf` mapping. -//! * A veto cancels a proposal, but the veto is not considered a vote. -//! * **Council proposal voting cancellation** -//! * The `on_finalise` signature is used in the module declaration to run anything that needs to be done at the end of the block. -//! In council proposal voting it calls a private function `end_block` with the current block as an argument, which loops through each proposal in storage whose voting period ends at the given block. For each proposal it calls `is_aux_sub_type` and destructures the return value. -//! The return value is a call to a function `cancel_referendum` with a `ref_index` (referendum index) argument that removes the referendum with that referendum index. -//! When the call to the return value `cancel_referendum` returns a value, then we know that this council proposal was elevated to the table of referenda and therefore has a referendum index. We also already know that it expires on this block, so we may proceed to run the associated block of code that actually cancels the referendum by: -//! * Dispatching event `TallyCancelation` to indicate that a voting tally has happened associated with a cancellation vote for the referendum associated with the given proposal. -//! * The council directly calling `internal_cancel_referendum` to remove the specific referendum with given referendum index, but doing so is only permitted if the voting tally for the proposal was a unanimous vote (i.e. no nays, no abstainers). -//! * **Council proposal voting elevation** -//! * The `on_finalise` signature is used in the module declaration to run anything that needs to be done at the end of the block. -//! In council proposal voting it calls a private function `end_block` with the current block as an argument, which loops through each proposal in storage whose voting period ends at the given block. For each proposal it calls `is_aux_sub_type` and destructures the return value. -//! When the call to `is_aux_sub_type` with the current proposal does not destructure to a function call that is able to cancel a referendum index associated with the proposal, then we know this council proposal has not yet been elevated to the table of referenda, so we may proceed to run the associated block of code that checks the vote tally to determine whether to start the referendum. -//! In the associated block of code it dispatches an event `TallyReferendum` to indicate the start of a voting tally for a referendum vote on the current proposal. -//! If the voting tally of the current proposal has more yay votes than the combination of all nay votes and abstainers, then it removes any veto imposed upon the council proposal (since the proposal voting period is expiring). -//! If the council voting tally was unanimous then it starts a referendum (elevating the proposal to the table of referendum) with a vote threshold of `SuperMajorityAgainst`. -//! Otherwise if there were any nay voters or abstainers at the end of council voting on the proposal then it starts a referendum (elevating the proposal to the table of referendum) with a vote threshold of `SimplyMajority`. -//! * **Council proposal voting approval/disapproval** -//! * When the **Council proposal voting tally** of yay votes for a council proposal reach the council proposal's threshold level during the council proposal voting period then the council approval is approved and elevated to the table of active referendum on the next block. -//! * Once the tally of votes result in the council proposal being approved or disapproved, we remove the motion from the `Voting` storage mapping, and remove the proposal hash from the list of active proposals Proposals. -//! * **Council proposal voting approval (simply majority / majority agreement) -//! * If the tally of yay votes for a council proposal reaches the council proposal's threshold level during the council proposal voting period and a majority council agreement occurs whereby a council proposal's tally from majority voting results in a simple majority (i.e. more explicit yay than nay votes), which signals a sensible and uncontroversial proposal, then it is approved. -//! When executed it is elevated to the table of active referendums on the next block, and a vote threshold of 'simple majority' is applied to the referendum. -//! * **Council proposal voting approval (unanimous / super majority against)** -//! * If a unanimous voting tally for the council proposal occurs and results in a unanimous council agreement (i.e. only yay votes), then it is approved. When executed it is elevated to the table of active referendum on the next block, and a vote threshold of 'super majority against' is applied to the referendum. -//! * It uses a negative AQB to encourage councillors not to abstain. A single veto from a councillor cancels the proposal and prevents the agreement. Council proposals submitted this way must have over 50% approval since abstention votes will be biased in favour of the proposal (alongside any nay votes). -//! * **Referenda** -//! * Each council or public proposal that is elevated to the table of referenda is instantly executed autonomously once their votes reach a threshold level of approval. +//! * `ProposalVoters` storage vector (containing account ids that have voted for the proposal's hash) is updated with the councillor's new vote. +//! * Councillor's vote storage tuple `CouncilVoteOf` is updated with a mapping between a tuple containing the proposal's hash, the councillor's account id, and their new vote. +//! * `Voting` storage mapping is updated with the councillor's vote. +//! * Note that `Voting` maps the proposal's hash to a tuple containing the corresponding proposal's index, vote threshold, and vectors containing both yay and nay voter account ids. +//! * **Council proposal voting rules** Duplicate votes from the same councillor are ignored. Councillors may swap their vote from yay to nay and vice versa. +//! * **Council proposal vote threshold** A council proposal that is created with a threshold level of one is voted upon and approved by the councillor that created it, and then executed. Whereas a council proposal with a threshold level of more than one is added to the `Voting` storage mapping. +//! * **Council proposal voting veto rules** A councillor may veto a proposal if it's stored in the `ProposalVoters` mapping, on condition that they have not vetoed it previously. Once a councillor vetoes a council proposal they cannot propose the proposal again until after a cooling off period that's measured in blocks. +//! * **Council proposal voting veto** If a councillors veto is valid then their veto is stored in `VetoedProposal` amongst other councillors that have vetoed the proposal. `VetoedProposal` maps the proposal's hash to a tuple comprising of the block number when the veto expires, and the account id of the vetoer. Vetoed proposals are removed from various storage locations, including the `Proposals` storage vector, the `ProposalsOf` storage mapping, the `ProposalVoters` storage mapping, and the `CouncilVoteOf` mapping. A veto cancels a proposal, but the veto is not considered a vote. +//! * **Council proposal voting cancellation** The `on_finalise` signature is used in the module declaration to run anything that needs to be done at the end of the block. In council proposal voting it calls a private function `end_block` with the current block as an argument, which loops through each proposal in storage whose voting period ends at the given block. For each proposal it calls `is_aux_sub_type` and destructures the return value. The return value is a call to a function `cancel_referendum` with a `ref_index` (referendum index) argument that removes the referendum with that referendum index. When the call to the return value `cancel_referendum` returns a value, then we know that this council proposal was elevated to the table of referenda and therefore has a referendum index. We also already know that it expires on this block, so we may proceed to cancels the referendum by: dispatching event `TallyCancelation` to indicate that a voting tally has happened associated with a cancellation vote for the referendum associated with the given proposal; and by the council directly calling `internal_cancel_referendum` to remove the specific referendum with the given referendum index, but doing so is only permitted if the voting tally for the proposal was a unanimous vote (i.e. no nays, no abstainers). +//! * **Council proposal voting elevation** The `on_finalise` signature is used in the module declaration to run anything that needs to be done at the end of the block. In council proposal voting it calls a private function `end_block` with the current block as an argument, which loops through each proposal in storage whose voting period ends at the given block. For each proposal it calls `is_aux_sub_type` and destructures the return value. When the call to `is_aux_sub_type` with the current proposal does not destructure to a function call that is able to cancel a referendum index associated with the proposal, then we know this council proposal has not yet been elevated to the table of referenda, so we may proceed to check the vote tally to determine whether to start the referendum. If it starts the referendum it dispatches an event `TallyReferendum` to indicate that a voting tally has started for the referendum. If the voting tally has more yay votes than the combination of all nay votes and abstainers, then it removes any veto imposed upon the council proposal (since the proposal voting period is expiring). If the council voting tally was unanimous then it starts a referendum (elevating the proposal to the table of referendum) with a vote threshold of `SuperMajorityAgainst`. Otherwise if there were any nay voters or abstainers at the end of the council voting period then it starts a referendum (elevating the proposal to the table of referendum) with a vote threshold of `SimplyMajority`. +//! * **Council proposal voting approval/disapproval** When the **council proposal voting tally** of yay votes reach its threshold level during its voting period then it's approved and elevated to the table of active referendum on the next block. Once the tally of votes results in the council proposal being approved or disapproved, we remove the motion from the `Voting` storage mapping, and remove the proposal hash from the list of active proposals `Proposals`. +//! * **Council proposal voting approval (simply majority / majority agreement)** If the tally of yay votes for a council proposal reaches its threshold level during its voting period and a majority council agreement occurs whereby its tally from majority voting results in a simple majority (i.e. more explicit yay than nay votes, which signals a sensible and uncontroversial proposal), then it is approved. When executed it is elevated to the table of active referenda on the next block, and a vote threshold of simple majority is applied to the referendum. +//! * **Council proposal voting approval (unanimous / super majority against)** If a unanimous voting tally for the council proposal occurs and results in a unanimous council agreement (i.e. only yay votes), then it is approved. When executed it is elevated to the table of active referenda on the next block, and a vote threshold of 'super majority against' is applied to the referendum. It uses a negative [AQB](https://docs.substrate.dev/docs/glossary#section-adaptive-quorum-biasing-aqb-) to encourage councillors not to abstain. A single veto from a councillor cancels the proposal and prevents the agreement. Council proposals submitted this way must have over 50% approval since abstention votes will be biased in favour of the proposal (alongside any nay votes). +//! * **Referenda** Each council or public proposal that is elevated to the table of referenda is instantly executed autonomously once its vote count reaches its threshold level for approval. //! //! #### Council Seats //! -//! * **Candidate approval voting call** -//! * Express candidate approval voting is a public call that anyone may execute by signing and submitting an extrinsic. -//! We ensure that information about the `origin` where the dispatch initiated is a signed account using `ensure_signed`. -//! It performs an `O(1)` operation that involves one extra DB entry and one DB change. -//! * **Candidate registration and vote index** -//! * Candidate approval votes are only considered before the presentation period and when the candidates have a registered list slot with an approved candidate index `VoteIndex` that exists. -//! * **Candidate voter's security bond for the first vote** -//! * If it is the voter’s first vote and its valid, then before enacting any operation and changing the storage, a "voter" security bond is deducted from the voter using the `reserve` function of the `Balances` module, as it may result in a major alteration of storage. The bond amount should be sufficient enough to cover any costs of the substantial execution in case the operation cannot proceed. The bond is a mitigation measure against the classical blockchain attack scenario since we cannot be certain that the operation will not require substantial computation. -//! The voter's account id is pushed onto the `Voters` vector that contains the list of present voters. -//! * **Candidate voter's subsequent votes (after their first vote)** -//! * If it is a subsequent vote from the voter and their vote is valid, then their: -//! * Vote is recorded in `LastActiveOf`, which maps their account id to the last cleared vote index that they were active at. -//! * Votes (i.e. yay or nay) for each candidate with a vote index is added to the `ApprovalsOf` mapping. -//! * **Candidate voter inactivity reaping prerequisites** -//! * Reaping inactive voter's is only considered valid by satisfying the following prerequisites: -//! * Before the presentation period. -//! * Both the reporter and the target have already voted and are recorded in `LastActiveOf`. -//! * Assumed vote index is after an inactivity grace period (vote indexes remaining after the target voter's last active vote and when their associated approval votes are uncertain). -//! * Both the given reporter's vote index and the given target's vote index exist. -//! * Candidates approved index `VoteIndex` exists and matches the vote index that the reporter assumed was correct. -//! * **Candidate voter inactivity reaping claim validity determination** -//! * Upon satisfying the **Candidate voter inactivity reaping prerequisites** we determine whether the reporter has made a "valid" claim that target account was inactive. If the claim is true then we remove the target's inactive account, otherwise we remove the account that falsely reported their inactivity. -//! * To determine the "validity" of the claim, we enumerate over two list iterators in parallel `approvals_of` (maps the account id of the target voter to their list of votes for the last vote index when their vote was active), and `candidates` (present list of candidate account id's). Then we deem the reporter's claim "invalid" if none of the following are true: -//! * If any of the candidate account idss has a list of votes to the last vote index, and; -//! * If any of the candidate account id's isn't the default, and; -//! * If using `RegisterInfoOf` and any of the candidate account id's maps to a corresponding vote index when they registered that is less than or equal to the target voter's last active vote index. This would indicate that the candidate registered before the last vote index `LastActiveOf` when the target voter was last active, and means it is a "valid" claim that the target voter was an inactive voter between the registration and the last activate vote. -//! * **Candidate voter inactivity reaping** -//! * Removing an inactive voter is a public call. It performs an `O(1)` operation that involves one fewer DB entry and one DB change. -//! * After determining the result of the claim "validity" we call `remove_voter` as follows, depending on the claim validity; -//! * If the claim was "valid" we delete the inactive voter using the associated vote index and their list of approval votes; OR -//! * If the claim was "invalid" we delete the reporter (due to the target account actually still being active). -//! * Lastly we perform the reaping as follows, depending the claim validity; -//! * If the claim was "valid" then we call `repatriate_reserved` to slash the target account of their "voter" bond and move that value from their reserved account balance to the free balance of the reporter (beneficiary), and emit a `VoterReaped` event. -//! * If the claim was "invalid" then we call `slash_reserved` to slash the reporter for their bad behaviour in making a false claim. -//! We slash the reporter's account by deducting a value from their reserved balance, and decrease the total amount of stake in the system by the amount that was slashed, then we emit a `BadReaperSlashed` event. +//! * **Candidate approval voting call** Express candidate approval voting is a public call that anyone may execute by signing and submitting an extrinsic. We ensure that information about the `origin` where the dispatch initiated is a signed account using `ensure_signed`. It performs an `O(1)` operation that involves one extra database entry and one database change. +//! * **Candidate registration and vote index** Candidate approval votes are only considered before the presentation period and for candidates that have a registered list slot with an approved candidate index `VoteIndex`. +//! * **Candidate voters security bond (for the first vote)** If it's the voter's first vote and its valid, then before enacting any operation and changing the storage, a security bond is deducted from them using the `reserve` function of the Balances module, as it may result in a major alteration of storage. The bond amount should be sufficient to cover any costs of the substantial execution in case the operation cannot proceed. The bond is a mitigation measure against the classical blockchain attack scenario since we cannot be certain that the operation will not require substantial computation. The voters account id is pushed onto the `Voters` vector that contains the list of present voters. +//! * **Candidate voters' subsequent votes (after their first vote)** If the voter makes a subsequent vote that's valid, then: their vote is recorded in `LastActiveOf`, which maps their account id to the last cleared vote index that they were active at; and the votes (i.e. yay or nay) for each candidate with a vote index is added to the `ApprovalsOf` mapping. +//! * **Candidate voter inactivity reaping prerequisites** Reaping inactive voters is only considered valid after satisfying the following prerequisites: It must occur before the presentation period; both the reporter and the target must have already voted and have been recorded in `LastActiveOf`; the assumed vote index occurs after an inactivity grace period (vote indexes remaining after the target voter's last active vote and when their associated approval votes are uncertain); both the given reporters' vote index and the given targets' vote index exist; the candidates' approved index `VoteIndex` exists and matches the vote index that the reporter assumed was correct. +//! * **Candidate voter inactivity reaping claim validity determination** Upon satisfying the **candidate voter inactivity reaping prerequisites**, we determine whether the reporter has made a valid claim that the target account was in fact inactive. If the claim is true then we remove the targets' inactive account, otherwise we remove the account that falsely reported their inactivity. To determine the validity of the claim, we enumerate over two lists in parallel: `approvals_of` (maps the account id of the target voter to their list of votes for the last vote index when their vote was active); and `candidates` (the current list of candidate account ids). Then if none of the following are true, we deem the reporters' claim invalid: If any of the candidate account ids has a list of votes to the last vote index; and if any of the candidate account ids isn't the default; and if using `RegisterInfoOf` and any of the candidate account ids maps to a corresponding vote index when they registered that is less than or equal to the target voters last active vote index. This would indicate that the candidate registered before the last vote index `LastActiveOf` when the target voter was last active, and means it is in fact a valid claim to state that the target voter was an inactive voter between their registration and the last activate vote. +//! * **Candidate voter inactivity reaping** Removing an inactive voter is a public call. It performs an `O(1)` operation that involves one fewer database entry and one database change. After determining the result of the claim validity, we call `remove_voter` as follows, depending on the claim validity: If the claim was valid we delete the inactive voter using the associated vote index and their list of approval votes; or if the claim was invalid we delete the reporter (due to the target account actually still being active). Lastly we perform the reaping as follows, depending the claim validity: If the claim was valid then we call `repatriate_reserved` to slash the target account of their voter bond and move that value from their reserved account balance to the free balance of the reporter (beneficiary), then emit a `VoterReaped` event; if the claim was invalid then we call `slash_reserved` to slash the reporter for their bad behaviour in making a false claim. The reporter's account is slashed by deducting a value from their reserved balance, and by decreasing the total amount of stake in the system by the amount that was slashed, then we emit a `BadReaperSlashed` event. //! //! ### Goals //! -//! The council system in Substrate is designed to make the following possible: +//! The Council module in Substrate is designed to make the following possible: //! -//! * Creation of Council proposals using the Council motion mechanism by Councillors. -//! * Validation of Council proposals. -//! * Tallying votes on Council proposals by Councillors during the proposals' voting period. -//! * Vetoing (postponement) of Council proposals through abstainment by Councillors for a cooldown period. -//! * Elevation of Council proposals to start an associated referenda on the Table of Referenda. -//! * Applying vote thresholds to referenda depending on their associated Council proposal voting approval tally. +//! * Creation of council proposals using the council motion mechanism by councillors. +//! * Validation of council proposals. +//! * Tallying votes of council proposals by councillors during the proposals' voting period. +//! * Vetoing (postponement) of council proposals through abstainment by councillors for a cooldown period. +//! * Elevation of council proposals to start an associated referenda on the table of referenda. +//! * Applying vote thresholds to referenda depending on their associated council proposal voting approval tally. //! * Instant autonomous execution of referenda once their vote tally reaches the vote threshold level of approval. -//! * Cancellation of Council proposals that were elevated as associated referenda on the Table of Referenda. +//! * Cancellation of council proposals that were elevated as associated referenda onto the table of referenda. //! * Candidate registration in list slots (necessary to receive candidate approval votes during the presentation period). -//! * Deduction of security bonds from Candidate voters. -//! * Express Council seat candidate approval voting. -//! * Reaping of Candidate voters due to valid claims of their inactivity by reporters. -//! * Reaping reporters that lodge invalid claims of Candidate voter inactivity. +//! * Deduction of security bonds from candidate voters. +//! * Express council seat candidate approval voting. +//! * Reaping of candidate voters due to valid claims of their inactivity by reporters. +//! * Reaping reporters that lodge invalid claims of candidate voter inactivity. //! //! ## Interface //! @@ -161,39 +98,51 @@ //! //! #### Council Motions //! -//! * `propose` - Creation of a Council proposal using the Council motion mechanism by a Councillor who provides a vote threshold. -//! * `vote` - Update the approval vote tally from active Councillors voting on a Council proposal. Approve and execute it when the vote tally reaches the vote threshold. Disapprove it when the potential votes remaining is less than the threshold. +//! * `propose` - Create a council proposal using the council motion mechanism by a councillor who provides a vote threshold. +//! * `vote` - Update the approval vote tally through active councillors voting on a council proposal. Approve and execute it when the vote tally reaches the vote threshold. Disapprove it when the potential votes remaining is less than the threshold. //! //! #### Council Seats //! -//! `set_approvals` - TODO -//! `proxy_set_approvals` - TODO -//! `reap_inactive_voter` - TODO -//! `retract_voter` - TODO -//! `submit_candidacy` - TODO -//! `present_winner` - TODO -//! `set_desired_seats` - TODO -//! `remove_member` - TODO -//! `set_presentation_duration` - TODO -//! `set_term_duration` - TODO -//! `on_finalize` - TODO +//! * `set_approvals` - Set candidate approvals. Approval slots stay valid as long as candidates in those slots are registered. +//! * `proxy_set_approvals` - Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in those slots are registered. +//! * `reap_inactive_voter` - Remove a voter. Can be called by anyone. Returns the voter deposit to the `signed` origin. +//! * `retract_voter` - Remove a voter. All votes are cancelled and the voter deposit is returned. +//! * `submit_candidacy` - Submit oneself for candidacy. Account must have enough transferrable funds in it to pay the bond. +//! * `present_winner` - Claim that the `signed` origin is one of the top candidates. +//! * `set_desired_seats` - Set the desired council member count. +//! * `remove_member` - Remove a council member immediately. A tally happens instantly (if not already in a presentation period) to fill the seat if removal means that the desired members are not met. +//! * `set_presentation_duration` - Set the presentation duration. +//! * `set_term_duration` - Set the term duration. +//! * `on_finalize` - Signature declaration that runs anything that needs to be done at the end of the block. //! //! #### Council Voting //! -//! `propose` - TODO -//! `vote` - TODO -//! `veto` - TODO -//! `set_cooloff_period` - TODO -//! `set_voting_period` - TODO -//! `on_finalize` - TODO -//! -//! Please refer to the [`Call`](./enum.Call.html) enum and its associated variants for documentation on each function. +//! * `propose` - Propose a council proposal. +//! * `vote` - Vote on a council proposal by a councillor. +//! * `veto` - Veto a council proposal by a councillor. +//! * `set_cooloff_period` - Specify cooling off period. +//! * `set_voting_period` - Specify voting period. +//! * `on_finalize` - Signature declaration that runs anything that needs to be done at the end of the block. //! //! ### Public Functions //! -//! Please refer to the [`Module`](https://crates.parity.io/srml_council/struct.Module.html) struct for details on publicly available functions. +//! #### Council Motions +//! +//! * `is_councillor` - Check if a councillor is a member of the active council. +//! +//! #### Council Seats +//! +//! * `presentation_active` - Check if we're currently in a presentation period. +//! * `is_a_candidate` - Check if a specific account id is a registered candidate. +//! * `next_vote_from` - Determine the block when a vote can occur. +//! * `next_tally` - The block number when the tally for the next election will occur. +//! +//! #### Council Voting //! -//! **Note:** When using the publicly exposed functions, you (the runtime developer) are responsible for implementing any necessary checks (e.g. that the sender is the signer) before calling a function that will affect storage. +//! * `is_vetoed` - Check if a council proposal has been vetoed. +//! * `will_still_be_councillor_at` - Check each account id of the active council to determine what block number they will still be active. +//! * `is_councillor` - Check if a given account id is a councillor. +//! * `tally` - Tally's council votes. //! //! ## Usage //!