From aa83f220a497467dc316b96510d33fff69fbf91a Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sat, 9 Mar 2019 14:59:38 +0100 Subject: [PATCH 01/21] initial doc for the staking module --- srml/staking/README.adoc | 120 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 srml/staking/README.adoc diff --git a/srml/staking/README.adoc b/srml/staking/README.adoc new file mode 100644 index 0000000000000..7662b82a19d08 --- /dev/null +++ b/srml/staking/README.adoc @@ -0,0 +1,120 @@ +# Staking Module + +The staking module is the means by which a set of network maintainers (known as _authorities_ in some contexts and _validators_ in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are __rewarded under normal operation__ but are held __at pain of “slash”__ should they be found not to bee discharging their duties properly. + + +## Overview + +### Terminology + +- **Staking**: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. +- **Validating**: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. (see [here]() for the details of how block production and finalization are separated) +- **Nominating**: The process of placing staked funds behind one or more validators in order to share in any reward and punishment, they take. +- **Stash account**: The account holding an owner's funds used for staking. +- **Controller account**: The account which controls an owner's funds for staking. +- **Era**: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. +- **Slash**: The punishment of a staker by reducing their funds. + +### Scenarios + +Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the [`bond()`](#todo) function. + +Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. + +A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the [`validate()`](#todo) call. + +A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the [`nominate()`](#todo) call. + +The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. + +Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the [`chill()`](#todo) call. + +## Public Interface + +The staking module contains many public storage items and (im)mutable functions. Please refer to the [rustdoc](#todo) to see the full list. + +## Usage Example + +### Bonding and Accepting Roles + +An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: + +``` +// bond account 3 as stash +// account 4 as controller +// with stash value 1500 units +// while the rewards get transferred to the controller account. +Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); +``` + +To state desire in becoming a validator: + +``` +// controller account 4 states desire for validation with the given preferences. +Staking::validate(Origin::signed(4), ValidatorPrefs::default()); +``` + +Note that, as mentioned, the stash account is transparent in such calls and only the controller initiates the function calls. + +Similarly, to state desire in nominating: + +``` +// controller account 4 nominates for account 10 and 20. +Staking::nominate(Origin::signed(4), vec![20, 10]); +``` + +Finally, account 4 can withdraw from any of the above roles via + +``` +Staking::chill(Origin::signed(4)); +``` + +### ??? + +TODO: What else could be a usage example here interesting for the user? Do we have any? + +## Implementation Details + +### Slot Stake + +The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ + +### Reward Calculation + + - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named [`SessionReward`](#todo). + - Once a new era is triggered, rewards are paid to the validators and the associated nominators. + - The validator can declare an amount that does not get shared with the nominators at each reward payout through their [`ValidatorPrefs`](#todo). This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. + - All entities who receive a reward have the option to choose their reward destination, through the [`Payee`](#todo) storage, to be one of the following: + - Controller account. + - Stash account, not increasing the staked value. + - Stash account, also increasing the staked value. + +### Slashing details + +- A validator can be _reported_ to be offline at any point via [`on_offline_validator`](#todo) public function. +- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in [`ValidatorPrefs`](#todo). On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. +- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, [`OfflineSlash`](#todo). +- Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. + - If the previous overflow, then `slot_stake` is used. + - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). + +### Election algorithm details. + +Current election algorithm is implemented based on Phragmen. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). + +## Extensibility + +// Details that the user can modify or customize to make their own + + +## Dependencies + +### GenesisConfig + +See [`chain_spec.rs`](#todo) for a list of attributed that can be provided. + +### Related Modules + +- [Balances](#todo): Used to manage values at stake. +- [Sessions](#todo): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's [`Validators`](#todo) at the end of each era. +- [System](#todo): Used to obtain block number and time, among other details. From b9d09bb7d751bc01480d813b1e1ac20eb1296362 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sat, 9 Mar 2019 15:04:47 +0100 Subject: [PATCH 02/21] Remove md style links. --- srml/staking/README.adoc | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/srml/staking/README.adoc b/srml/staking/README.adoc index 7662b82a19d08..931ff8c4cb5c2 100644 --- a/srml/staking/README.adoc +++ b/srml/staking/README.adoc @@ -17,21 +17,21 @@ The staking module is the means by which a set of network maintainers (known as ### Scenarios -Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the [`bond()`](#todo) function. +Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. -A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the [`validate()`](#todo) call. +A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. -A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the [`nominate()`](#todo) call. +A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. -Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the [`chill()`](#todo) call. +Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the [`chill()` call. ## Public Interface -The staking module contains many public storage items and (im)mutable functions. Please refer to the [rustdoc](#todo) to see the full list. +The staking module contains many public storage items and (im)mutable functions. Please refer to the rustdoc to see the full list. ## Usage Example @@ -69,8 +69,6 @@ Finally, account 4 can withdraw from any of the above roles via Staking::chill(Origin::signed(4)); ``` -### ??? - TODO: What else could be a usage example here interesting for the user? Do we have any? ## Implementation Details @@ -81,19 +79,19 @@ The term `slot_stake` will be used throughout this section. It refers to a value ### Reward Calculation - - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named [`SessionReward`](#todo). + - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. - Once a new era is triggered, rewards are paid to the validators and the associated nominators. - - The validator can declare an amount that does not get shared with the nominators at each reward payout through their [`ValidatorPrefs`](#todo). This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. - - All entities who receive a reward have the option to choose their reward destination, through the [`Payee`](#todo) storage, to be one of the following: + - The validator can declare an amount that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. + - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage, to be one of the following: - Controller account. - Stash account, not increasing the staked value. - Stash account, also increasing the staked value. ### Slashing details -- A validator can be _reported_ to be offline at any point via [`on_offline_validator`](#todo) public function. -- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in [`ValidatorPrefs`](#todo). On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. -- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, [`OfflineSlash`](#todo). +- A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. +- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. +- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. - Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. - If the previous overflow, then `slot_stake` is used. - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). @@ -111,10 +109,10 @@ Current election algorithm is implemented based on Phragmen. The reference imple ### GenesisConfig -See [`chain_spec.rs`](#todo) for a list of attributed that can be provided. +See `chain_spec.rs` for a list of attributed that can be provided. ### Related Modules -- [Balances](#todo): Used to manage values at stake. -- [Sessions](#todo): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's [`Validators`](#todo) at the end of each era. -- [System](#todo): Used to obtain block number and time, among other details. +- Balances: Used to manage values at stake. +- Sessions: Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. +- System: Used to obtain block number and time, among other details. From 7df2b19ff20e97f22213f69e32b6922b42fd3dcc Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sat, 9 Mar 2019 15:07:12 +0100 Subject: [PATCH 03/21] Remove todos. --- srml/staking/README.adoc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/srml/staking/README.adoc b/srml/staking/README.adoc index 931ff8c4cb5c2..0ef8d4b90876a 100644 --- a/srml/staking/README.adoc +++ b/srml/staking/README.adoc @@ -8,7 +8,7 @@ The staking module is the means by which a set of network maintainers (known as ### Terminology - **Staking**: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. -- **Validating**: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. (see [here]() for the details of how block production and finalization are separated) +- **Validating**: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. - **Nominating**: The process of placing staked funds behind one or more validators in order to share in any reward and punishment, they take. - **Stash account**: The account holding an owner's funds used for staking. - **Controller account**: The account which controls an owner's funds for staking. @@ -69,7 +69,6 @@ Finally, account 4 can withdraw from any of the above roles via Staking::chill(Origin::signed(4)); ``` -TODO: What else could be a usage example here interesting for the user? Do we have any? ## Implementation Details @@ -104,7 +103,6 @@ Current election algorithm is implemented based on Phragmen. The reference imple // Details that the user can modify or customize to make their own - ## Dependencies ### GenesisConfig From 28b959b5675a2f7208b142cf65b23b4d298550ec Mon Sep 17 00:00:00 2001 From: kianenigma Date: Sat, 9 Mar 2019 15:11:53 +0100 Subject: [PATCH 04/21] Add rust code types --- srml/staking/README.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srml/staking/README.adoc b/srml/staking/README.adoc index 0ef8d4b90876a..fc25f5a704909 100644 --- a/srml/staking/README.adoc +++ b/srml/staking/README.adoc @@ -39,7 +39,7 @@ The staking module contains many public storage items and (im)mutable functions. An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: -``` +```rust // bond account 3 as stash // account 4 as controller // with stash value 1500 units @@ -49,7 +49,7 @@ Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); To state desire in becoming a validator: -``` +```rust // controller account 4 states desire for validation with the given preferences. Staking::validate(Origin::signed(4), ValidatorPrefs::default()); ``` @@ -58,14 +58,14 @@ Note that, as mentioned, the stash account is transparent in such calls and only Similarly, to state desire in nominating: -``` +```rust // controller account 4 nominates for account 10 and 20. Staking::nominate(Origin::signed(4), vec![20, 10]); ``` Finally, account 4 can withdraw from any of the above roles via -``` +```rust Staking::chill(Origin::signed(4)); ``` From 91be68b9a7d029b33331c58a89a7884e57366533 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 11 Mar 2019 16:10:27 +0100 Subject: [PATCH 05/21] Rename and fix review notes. --- srml/staking/README.adoc | 116 --------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 srml/staking/README.adoc diff --git a/srml/staking/README.adoc b/srml/staking/README.adoc deleted file mode 100644 index fc25f5a704909..0000000000000 --- a/srml/staking/README.adoc +++ /dev/null @@ -1,116 +0,0 @@ -# Staking Module - -The staking module is the means by which a set of network maintainers (known as _authorities_ in some contexts and _validators_ in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are __rewarded under normal operation__ but are held __at pain of “slash”__ should they be found not to bee discharging their duties properly. - - -## Overview - -### Terminology - -- **Staking**: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. -- **Validating**: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. -- **Nominating**: The process of placing staked funds behind one or more validators in order to share in any reward and punishment, they take. -- **Stash account**: The account holding an owner's funds used for staking. -- **Controller account**: The account which controls an owner's funds for staking. -- **Era**: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. -- **Slash**: The punishment of a staker by reducing their funds. - -### Scenarios - -Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. - -Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. - -A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. - -A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. - -The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. - -Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the [`chill()` call. - -## Public Interface - -The staking module contains many public storage items and (im)mutable functions. Please refer to the rustdoc to see the full list. - -## Usage Example - -### Bonding and Accepting Roles - -An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: - -```rust -// bond account 3 as stash -// account 4 as controller -// with stash value 1500 units -// while the rewards get transferred to the controller account. -Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); -``` - -To state desire in becoming a validator: - -```rust -// controller account 4 states desire for validation with the given preferences. -Staking::validate(Origin::signed(4), ValidatorPrefs::default()); -``` - -Note that, as mentioned, the stash account is transparent in such calls and only the controller initiates the function calls. - -Similarly, to state desire in nominating: - -```rust -// controller account 4 nominates for account 10 and 20. -Staking::nominate(Origin::signed(4), vec![20, 10]); -``` - -Finally, account 4 can withdraw from any of the above roles via - -```rust -Staking::chill(Origin::signed(4)); -``` - - -## Implementation Details - -### Slot Stake - -The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ - -### Reward Calculation - - - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. - - Once a new era is triggered, rewards are paid to the validators and the associated nominators. - - The validator can declare an amount that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. - - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage, to be one of the following: - - Controller account. - - Stash account, not increasing the staked value. - - Stash account, also increasing the staked value. - -### Slashing details - -- A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. -- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. -- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. -- Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. - - If the previous overflow, then `slot_stake` is used. - - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). - -### Election algorithm details. - -Current election algorithm is implemented based on Phragmen. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). - -## Extensibility - -// Details that the user can modify or customize to make their own - -## Dependencies - -### GenesisConfig - -See `chain_spec.rs` for a list of attributed that can be provided. - -### Related Modules - -- Balances: Used to manage values at stake. -- Sessions: Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. -- System: Used to obtain block number and time, among other details. From 5912ff59c4f7ac3dde384bc78ee0872cde1f5626 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 11 Mar 2019 16:11:13 +0100 Subject: [PATCH 06/21] Add new md file --- srml/staking/README.md | 139 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 srml/staking/README.md diff --git a/srml/staking/README.md b/srml/staking/README.md new file mode 100644 index 0000000000000..45d706ae7009a --- /dev/null +++ b/srml/staking/README.md @@ -0,0 +1,139 @@ +# Staking Module + + +The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly[[1](#references)]. + +### Overview + +### Terminology + + +- Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. +- Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. +- Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. +- Stash account: The account holding an owner's funds used for staking. +- Controller account: The account which controls am owner's funds for staking. +- Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. +- Slash: The punishment of a staker by reducing their funds. + +### Goals + + +The staking system in Substrate NPoS is designed to achieve three goals: +- It should be possible to stake funds that are controlled by a cold wallet. +- It should be possible to withdraw some, or deposit more, funds without interrupting the role of t. +- It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. + +### Scenarios + +#### Staking + +Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. + +Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. + +#### Validating + +A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. + +#### Nomination + +A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. + +#### Rewards and Slash + +The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. + +Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the `chill()` call. + +## Public Interface + +The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the `Module` struct definition for more details. + +## Usage Example + +### Bonding and Accepting Roles + +An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: + +```rust +// bond account 3 as stash +// account 4 as controller +// with stash value 1500 units +// while the rewards get transferred to the controller account. +Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); +``` + +To state desire in becoming a validator: + +```rust +// controller account 4 states desire for validation with the given preferences. +Staking::validate(Origin::signed(4), ValidatorPrefs::default()); +``` + +Note that, as mentioned, the stash account is transparent in such calls and only the controller initiates the function calls. + +Similarly, to state desire in nominating: + +```rust +// controller account 4 nominates for account 10 and 20. +Staking::nominate(Origin::signed(4), vec![20, 10]); +``` + +Finally, account 4 can withdraw from any of the above roles via + +```rust +Staking::chill(Origin::signed(4)); +``` + + +## Implementation Details + +### Slot Stake + +The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ + +### Reward Calculation + + - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. + - Once a new era is triggered, rewards are paid to the validators and the associated nominators. + - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. + - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage (see `set_payee()`), to be one of the following: + - Controller account. + - Stash account, not increasing the staked value. + - Stash account, also increasing the staked value. + +### Slashing details + +- A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. +- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. +- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. +- Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. + - If the previous overflow, then `slot_stake` is used. + - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). + +### Additional Fund Management Operations + +Any funds already placed into stash can be the target of the following operations: + +- The controller account can free an portion (or all) of the funds using the `unbond()` call. Note that the funds are not immediately accessible, instead, a duration denoted by `BondingDuration` number of eras must pass until the funds can be actually removed. +- To actually remove the funds, once the bonding duration is over, the `withdraw_unbonded()` can be used. +- As opposed to the above, additional funds can be added to the stash account via the `bond_extra()` transaction call. + +### Election algorithm details. + +Current election algorithm is implemented based on Phragmén. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). + +## GenesisConfig + +See the [`GensisConfig`](https://crates.parity.io/srml_staking/struct.GenesisConfig.html) for a list of attributed that can be provided. + +## Related Modules + +- [**Balances**](https://crates.parity.io/srml_balances/index.html): Used to manage values at stake. +- [**Sessions**](https://crates.parity.io/srml_session/index.html): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. +- [**System**](https://crates.parity.io/srml_system/index.html): Used to obtain block number and time, among other details. + +# References + +1. This document is written as a more verbose version of the original [Staking.md]() file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. \ No newline at end of file From 64ca546bfed1e5ae62bae883365616677a74bf0b Mon Sep 17 00:00:00 2001 From: Kian Peymani Date: Mon, 11 Mar 2019 16:17:03 +0100 Subject: [PATCH 07/21] Final touches. --- srml/staking/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srml/staking/README.md b/srml/staking/README.md index 45d706ae7009a..589d881e1ac86 100644 --- a/srml/staking/README.md +++ b/srml/staking/README.md @@ -1,7 +1,7 @@ # Staking Module -The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly[[1](#references)]. +The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly [[1](#references)]. ### Overview @@ -34,7 +34,7 @@ Any account pair successfully placed at stake can accept three possible roles, n #### Validating -A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Unlike nominating, bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. +A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. #### Nomination @@ -48,7 +48,7 @@ Finally, any of the roles above can choose to temporarily step back and just chi ## Public Interface -The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the `Module` struct definition for more details. +The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. ## Usage Example @@ -136,4 +136,4 @@ See the [`GensisConfig`](https://crates.parity.io/srml_staking/struct.GenesisCon # References -1. This document is written as a more verbose version of the original [Staking.md]() file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. \ No newline at end of file +1. This document is written as a more verbose version of the original [Staking.md](./Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. From a8ba78e502341ed598c5da7c9a250772c1c18821 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 11 Mar 2019 18:29:37 +0100 Subject: [PATCH 08/21] Migrate compleatly to rustdoc --- srml/staking/README.md | 139 --------------------------------------- srml/staking/src/lib.rs | 141 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 140 deletions(-) delete mode 100644 srml/staking/README.md diff --git a/srml/staking/README.md b/srml/staking/README.md deleted file mode 100644 index 589d881e1ac86..0000000000000 --- a/srml/staking/README.md +++ /dev/null @@ -1,139 +0,0 @@ -# Staking Module - - -The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly [[1](#references)]. - -### Overview - -### Terminology - - -- Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. -- Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. -- Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. -- Stash account: The account holding an owner's funds used for staking. -- Controller account: The account which controls am owner's funds for staking. -- Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. -- Slash: The punishment of a staker by reducing their funds. - -### Goals - - -The staking system in Substrate NPoS is designed to achieve three goals: -- It should be possible to stake funds that are controlled by a cold wallet. -- It should be possible to withdraw some, or deposit more, funds without interrupting the role of t. -- It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. - -### Scenarios - -#### Staking - -Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. - -Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. - -#### Validating - -A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. - -#### Nomination - -A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. - -#### Rewards and Slash - -The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. - -Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the `chill()` call. - -## Public Interface - -The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. - -## Usage Example - -### Bonding and Accepting Roles - -An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: - -```rust -// bond account 3 as stash -// account 4 as controller -// with stash value 1500 units -// while the rewards get transferred to the controller account. -Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); -``` - -To state desire in becoming a validator: - -```rust -// controller account 4 states desire for validation with the given preferences. -Staking::validate(Origin::signed(4), ValidatorPrefs::default()); -``` - -Note that, as mentioned, the stash account is transparent in such calls and only the controller initiates the function calls. - -Similarly, to state desire in nominating: - -```rust -// controller account 4 nominates for account 10 and 20. -Staking::nominate(Origin::signed(4), vec![20, 10]); -``` - -Finally, account 4 can withdraw from any of the above roles via - -```rust -Staking::chill(Origin::signed(4)); -``` - - -## Implementation Details - -### Slot Stake - -The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ - -### Reward Calculation - - - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. - - Once a new era is triggered, rewards are paid to the validators and the associated nominators. - - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. - - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage (see `set_payee()`), to be one of the following: - - Controller account. - - Stash account, not increasing the staked value. - - Stash account, also increasing the staked value. - -### Slashing details - -- A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. -- Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. -- Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. -- Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. - - If the previous overflow, then `slot_stake` is used. - - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). - -### Additional Fund Management Operations - -Any funds already placed into stash can be the target of the following operations: - -- The controller account can free an portion (or all) of the funds using the `unbond()` call. Note that the funds are not immediately accessible, instead, a duration denoted by `BondingDuration` number of eras must pass until the funds can be actually removed. -- To actually remove the funds, once the bonding duration is over, the `withdraw_unbonded()` can be used. -- As opposed to the above, additional funds can be added to the stash account via the `bond_extra()` transaction call. - -### Election algorithm details. - -Current election algorithm is implemented based on Phragmén. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). - -## GenesisConfig - -See the [`GensisConfig`](https://crates.parity.io/srml_staking/struct.GenesisConfig.html) for a list of attributed that can be provided. - -## Related Modules - -- [**Balances**](https://crates.parity.io/srml_balances/index.html): Used to manage values at stake. -- [**Sessions**](https://crates.parity.io/srml_session/index.html): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. -- [**System**](https://crates.parity.io/srml_system/index.html): Used to obtain block number and time, among other details. - -# References - -1. This document is written as a more verbose version of the original [Staking.md](./Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index b96cb8bbf630a..b038fb550efc5 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -16,7 +16,146 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Staking manager: Periodically determines the best set of validators. +//! # Staking Module +//! +//! +//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly [[1](#references)]. +//! +//! ### Overview +//! +//! ### Terminology +//! +//! +//! - Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. +//! - Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. +//! - Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. +//! - Stash account: The account holding an owner's funds used for staking. +//! - Controller account: The account which controls am owner's funds for staking. +//! - Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. +//! - Slash: The punishment of a staker by reducing their funds. +//! +//! ### Goals +//! +//! +//! The staking system in Substrate NPoS is designed to achieve three goals: +//! - It should be possible to stake funds that are controlled by a cold wallet. +//! - It should be possible to withdraw some, or deposit more, funds without interrupting the role of t. +//! - It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. +//! +//! ### Scenarios +//! +//! #### Staking +//! +//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. +//! +//! Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. +//! +//! #### Validating +//! +//! A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. +//! +//! #### Nomination +//! +//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. +//! +//! #### Rewards and Slash +//! +//! The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. +//! +//! Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the `chill()` call. +//! +//! ## Public Interface +//! +//! The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. +//! +//! ## Usage Example +//! +//! ### Bonding and Accepting Roles +//! +//! An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: +//! +//! ```rust +//! // bond account 3 as stash +//! // account 4 as controller +//! // with stash value 1500 units +//! // while the rewards get transferred to the controller account. +//! Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); +//! ``` +//! +//! To state desire in becoming a validator: +//! +//! ```rust +//! // controller account 4 states desire for validation with the given preferences. +//! Staking::validate(Origin::signed(4), ValidatorPrefs::default()); +//! ``` +//! +//! Note that, as mentioned, the stash account is transparent in such calls and only the controller initiates the function calls. +//! +//! Similarly, to state desire in nominating: +//! +//! ```rust +//! // controller account 4 nominates for account 10 and 20. +//! Staking::nominate(Origin::signed(4), vec![20, 10]); +//! ``` +//! +//! Finally, account 4 can withdraw from any of the above roles via +//! +//! ```rust +//! Staking::chill(Origin::signed(4)); +//! ``` +//! +//! +//! ## Implementation Details +//! +//! ### Slot Stake +//! +//! The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ +//! +//! ### Reward Calculation +//! +//! - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. +//! - Once a new era is triggered, rewards are paid to the validators and the associated nominators. +//! - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. +//! - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage (see `set_payee()`), to be one of the following: +//! - Controller account. +//! - Stash account, not increasing the staked value. +//! - Stash account, also increasing the staked value. +//! +//! ### Slashing details +//! +//! - A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. +//! - Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. +//! - Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. +//! - Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. +//! - If the previous overflow, then `slot_stake` is used. +//! - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). +//! +//! ### Additional Fund Management Operations +//! +//! Any funds already placed into stash can be the target of the following operations: +//! +//! - The controller account can free an portion (or all) of the funds using the `unbond()` call. Note that the funds are not immediately accessible, instead, a duration denoted by `BondingDuration` number of eras must pass until the funds can be actually removed. +//! - To actually remove the funds, once the bonding duration is over, the `withdraw_unbonded()` can be used. +//! - As opposed to the above, additional funds can be added to the stash account via the `bond_extra()` transaction call. +//! +//! ### Election algorithm details. +//! +//! Current election algorithm is implemented based on Phragmén. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). +//! +//! ## GenesisConfig +//! +//! See the [`GensisConfig`](https://crates.parity.io/srml_staking/struct.GenesisConfig.html) for a list of attributed that can be provided. +//! +//! ## Related Modules +//! +//! - [**Balances**](https://crates.parity.io/srml_balances/index.html): Used to manage values at stake. +//! - [**Sessions**](https://crates.parity.io/srml_session/index.html): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. +//! - [**System**](https://crates.parity.io/srml_system/index.html): Used to obtain block number and time, among other details. +//! +//! # References +//! +//! 1. This document is written as a more verbose version of the original [Staking.md](./Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. + #![cfg_attr(not(feature = "std"), no_std)] From 982d7e80426189983f561fe7879a3cfbfd4435cf Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 11 Mar 2019 18:29:58 +0100 Subject: [PATCH 09/21] Update link --- srml/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index b038fb550efc5..764b63cb82de2 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -154,7 +154,7 @@ //! //! # References //! -//! 1. This document is written as a more verbose version of the original [Staking.md](./Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. +//! 1. This document is written as a more verbose version of the original [Staking.md](../Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. #![cfg_attr(not(feature = "std"), no_std)] From 4a572a28e8c6c4cd69d779969ebd424b2d431403 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Mon, 11 Mar 2019 18:43:12 +0100 Subject: [PATCH 10/21] Fix heading --- srml/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 764b63cb82de2..5c2056c179bbb 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -21,7 +21,7 @@ //! //! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly [[1](#references)]. //! -//! ### Overview +//! ## Overview //! //! ### Terminology //! From 89682a64d4b99fa98c33c85200bab8d244c0873c Mon Sep 17 00:00:00 2001 From: kianenigma Date: Tue, 12 Mar 2019 16:06:07 +0100 Subject: [PATCH 11/21] Final touches wrt the new template. --- srml/staking/src/lib.rs | 51 ++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index b311cba1fcf81..c417955c49b59 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -19,7 +19,7 @@ //! # Staking Module //! //! -//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly [[1](#references)]. +//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly. //! //! ## Overview //! @@ -32,7 +32,7 @@ //! - Stash account: The account holding an owner's funds used for staking. //! - Controller account: The account which controls am owner's funds for staking. //! - Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. -//! - Slash: The punishment of a staker by reducing their funds. +//! - Slash: The punishment of a staker by reducing their funds ([reference](#references)). //! //! ### Goals //! @@ -64,17 +64,30 @@ //! //! Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the `chill()` call. //! -//! ## Public Interface +//! ## Interface //! -//! The staking module contains many public storage items and (im)mutable, and dispatchable, functions. Please refer to the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. +//! ### Types //! -//! ## Usage Example +//! - `Currency`: Used as the measurement means of staking and funds management. +//! +//! ### Dispatchable //! -//! ### Bonding and Accepting Roles +//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and and change their role, alongside some helper funcitons to get/set the metadata of the module. +//! +//! Please refer to the [`Call`](https://crates.parity.io/srml_staking/enum.Call.html) enum and its associated functions for a detailed list of dispatchable functions. +//! +//! ### Public +//! The staking module contains many public storage items and (im)mutable functions. Please refer to the [struct list](#structs) below and the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! ### Snippet: Bonding and Accepting Roles //! //! An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: //! -//! ```rust +//! ```rust,ignore //! // bond account 3 as stash //! // account 4 as controller //! // with stash value 1500 units @@ -84,7 +97,7 @@ //! //! To state desire in becoming a validator: //! -//! ```rust +//! ```rust,ignore //! // controller account 4 states desire for validation with the given preferences. //! Staking::validate(Origin::signed(4), ValidatorPrefs::default()); //! ``` @@ -93,18 +106,17 @@ //! //! Similarly, to state desire in nominating: //! -//! ```rust +//! ```rust,ignore //! // controller account 4 nominates for account 10 and 20. //! Staking::nominate(Origin::signed(4), vec![20, 10]); //! ``` //! //! Finally, account 4 can withdraw from any of the above roles via //! -//! ```rust +//! ```rust,ignore //! Staking::chill(Origin::signed(4)); //! ``` //! -//! //! ## Implementation Details //! //! ### Slot Stake @@ -154,7 +166,7 @@ //! //! # References //! -//! 1. This document is written as a more verbose version of the original [Staking.md](../Staking.md) file. Some sections, (denoted by `[1]`) are taken directly from the aforementioned document. +//! 1. This document is written as a more verbose version of the original [Staking.md](../Staking.md) file. Some sections, are taken directly from the aforementioned document. #![cfg_attr(not(feature = "std"), no_std)] @@ -424,6 +436,7 @@ decl_module! { /// Take the origin account as a stash and lock up `value` of its balance. `controller` will be the /// account that controls it. + /// The dispatch origin for this call must be _Signed_. fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination) { let stash = ensure_signed(origin)?; @@ -449,7 +462,7 @@ decl_module! { /// /// Use this if there are additional funds in your stash account that you wish to bond. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn bond_extra(origin, max_additional: BalanceOf) { let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -470,7 +483,7 @@ decl_module! { /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move /// the funds out of management ready for transfer. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// /// See also [`Call::withdraw_unbonded`]. fn unbond(origin, #[compact] value: BalanceOf) { @@ -500,7 +513,7 @@ decl_module! { /// This essentially frees up that balance to be used by the stash account to do /// whatever it wants. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// /// See also [`Call::unbond`]. fn withdraw_unbonded(origin) { @@ -514,7 +527,7 @@ decl_module! { /// /// Effects will be felt at the beginning of the next era. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn validate(origin, prefs: ValidatorPrefs>) { let controller = ensure_signed(origin)?; let _ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -527,7 +540,7 @@ decl_module! { /// /// Effects will be felt at the beginning of the next era. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn nominate(origin, targets: Vec<::Source>) { let controller = ensure_signed(origin)?; let _ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -545,7 +558,7 @@ decl_module! { /// /// Effects will be felt at the beginning of the next era. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn chill(origin) { let controller = ensure_signed(origin)?; let _ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -557,7 +570,7 @@ decl_module! { /// /// Effects will be felt at the beginning of the next era. /// - /// NOTE: This call must be made by the controller, not the stash. + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn set_payee(origin, payee: RewardDestination) { let controller = ensure_signed(origin)?; let _ledger = Self::ledger(&controller).ok_or("not a controller")?; From 956ec9634c822986b0dff12e2d248528faa9b761 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Tue, 12 Mar 2019 16:11:34 +0100 Subject: [PATCH 12/21] Remove empty prereq. --- srml/staking/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index c417955c49b59..f28bed03e463d 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -81,7 +81,6 @@ //! //! ## Usage //! -//! ### Prerequisites //! //! ### Snippet: Bonding and Accepting Roles //! From 2879e1d6713398801a1294f0ce999ebf3bb5995d Mon Sep 17 00:00:00 2001 From: kianenigma Date: Tue, 12 Mar 2019 16:58:28 +0100 Subject: [PATCH 13/21] Fix more reviews --- srml/staking/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index f28bed03e463d..68b62b2ede549 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -74,7 +74,7 @@ //! //! The Dispatchable functions of the staking module enable the steps needed for entities to accept and and change their role, alongside some helper funcitons to get/set the metadata of the module. //! -//! Please refer to the [`Call`](https://crates.parity.io/srml_staking/enum.Call.html) enum and its associated functions for a detailed list of dispatchable functions. +//! Please refer to the [`Call`] enum and its associated variants for a detailed list of dispatchable functions. //! //! ### Public //! The staking module contains many public storage items and (im)mutable functions. Please refer to the [struct list](#structs) below and the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. @@ -155,7 +155,7 @@ //! //! ## GenesisConfig //! -//! See the [`GensisConfig`](https://crates.parity.io/srml_staking/struct.GenesisConfig.html) for a list of attributed that can be provided. +//! See the [`GensisConfig`] for a list of attributed that can be provided. //! //! ## Related Modules //! From 105723b1be449f4e72d634bd9735227369508719 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Tue, 12 Mar 2019 18:47:48 +0100 Subject: [PATCH 14/21] Some final nits. --- srml/staking/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 68b62b2ede549..ada23a39d5968 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -19,7 +19,7 @@ //! # Staking Module //! //! -//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly. +//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharging their duties properly. //! //! ## Overview //! @@ -39,14 +39,14 @@ //! //! The staking system in Substrate NPoS is designed to achieve three goals: //! - It should be possible to stake funds that are controlled by a cold wallet. -//! - It should be possible to withdraw some, or deposit more, funds without interrupting the role of t. +//! - It should be possible to withdraw some, or deposit more, funds without interrupting the role of an entity. //! - It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. //! //! ### Scenarios //! //! #### Staking //! -//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the later, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. +//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the latter, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. //! //! Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. //! @@ -56,7 +56,7 @@ //! //! #### Nomination //! -//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share at the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. +//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share of the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. //! //! #### Rewards and Slash //! @@ -72,7 +72,7 @@ //! //! ### Dispatchable //! -//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and and change their role, alongside some helper funcitons to get/set the metadata of the module. +//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and change their role, alongside some helper functions to get/set the metadata of the module. //! //! Please refer to the [`Call`] enum and its associated variants for a detailed list of dispatchable functions. //! @@ -137,7 +137,7 @@ //! - A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. //! - Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. //! - Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. -//! - Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. +//! - Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it is calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. //! - If the previous overflow, then `slot_stake` is used. //! - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). //! From 5567859b677636dcab85b758ef5c3555f4c00b8d Mon Sep 17 00:00:00 2001 From: kianenigma Date: Thu, 14 Mar 2019 14:05:47 +0100 Subject: [PATCH 15/21] Fix some side issues. --- node/executor/src/lib.rs | 16 +--------------- srml/staking/src/lib.rs | 2 +- srml/staking/src/phragmen.rs | 34 +++++++++++++++------------------- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 84b2de336ed58..cc5992a514555 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -445,13 +445,7 @@ mod tests { ] ); - // let mut digest = generic::Digest::::default(); - // digest.push(Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![ - // (Keyring::Charlie.to_raw_public().into(), 1), - // (Keyring::Bob.to_raw_public().into(), 1), - // (Keyring::Alice.to_raw_public().into(), 1), - // ]))); - let digest = generic::Digest::::default(); // TODO test this + let digest = generic::Digest::::default(); assert_eq!(Header::decode(&mut &block2.0[..]).unwrap().digest, digest); (block1, block2) @@ -584,14 +578,6 @@ mod tests { phase: Phase::Finalization, event: Event::session(session::RawEvent::NewSession(1)) }, - // EventRecord { // TODO: this might be wrong. - // phase: Phase::Finalization, - // event: Event::grandpa(::grandpa::RawEvent::NewAuthorities(vec![ - // (Keyring::Charlie.to_raw_public().into(), 1), - // (Keyring::Bob.to_raw_public().into(), 1), - // (Keyring::Alice.to_raw_public().into(), 1), - // ])), - // }, EventRecord { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Spending(0)) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index bd354e0bf10e2..0311fdf618c2e 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -811,7 +811,7 @@ impl Module { /// Select a new validator set from the assembled stakers and their role preferences. /// - /// @returns the new SlotStake value. + /// returns the new SlotStake value. fn select_validators() -> BalanceOf { // Map of (would-be) validator account to amount of stake backing it. diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs index bdaed1fee9760..d67612755bc0d 100644 --- a/srml/staking/src/phragmen.rs +++ b/srml/staking/src/phragmen.rs @@ -69,25 +69,25 @@ pub struct Vote { /// /// Reference implementation: https://github.com/w3f/consensus /// -/// @returns a vector of elected candidates +/// returns a vector of elected candidates pub fn elect( get_rounds: FR, get_validators: FV, get_nominators: FN, stash_of: FS, minimum_validator_count: usize, - ) -> Vec>> where - FR: Fn() -> usize, - FV: Fn() -> Box>) - >>, - FN: Fn() -> Box) - >>, - FS: Fn(T::AccountId) -> BalanceOf, +) -> Vec>> where + FR: Fn() -> usize, + FV: Fn() -> Box>) + >>, + FN: Fn() -> Box) + >>, + FS: Fn(T::AccountId) -> BalanceOf, { let rounds = get_rounds(); - let mut elected_candidates = vec![]; + let mut elected_candidates; // 1- Pre-process candidates and place them in a container let mut candidates = get_validators().map(|(who, _)| { @@ -130,6 +130,7 @@ pub fn elect( // 4- If we have more candidates then needed, run Phragmén. if candidates.len() > rounds { + elected_candidates = Vec::with_capacity(rounds); // Main election loop for _round in 0..rounds { // Loop 1: initialize score @@ -177,7 +178,6 @@ pub fn elect( } elected_candidates.push(winner); - } // end of all rounds // 4.1- Update backing stake of candidates and nominators @@ -185,15 +185,11 @@ pub fn elect( for v in &mut n.nominees { // if the target of this vote is among the winners, otherwise let go. if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == v.who) { - v.backing_stake = as As>::sa( - n.stake.as_() - * *v.load - / *n.load - ); + v.backing_stake = as As>::sa(n.stake.as_() * *v.load / *n.load); c.exposure.total += v.backing_stake; // Update IndividualExposure of those who nominated and their vote won c.exposure.others.push( - IndividualExposure {who: n.who.clone(), value: v.backing_stake } + IndividualExposure { who: n.who.clone(), value: v.backing_stake } ); } } @@ -208,7 +204,7 @@ pub fn elect( if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == v.who) { c.exposure.total += n.stake; c.exposure.others.push( - IndividualExposure {who: n.who.clone(), value: n.stake } + IndividualExposure { who: n.who.clone(), value: n.stake } ); } } From e739361fccf59f4119b4c41e1336e8f482a845b0 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 15 Mar 2019 10:56:03 +0100 Subject: [PATCH 16/21] Fix another set of reviews --- srml/staking/src/lib.rs | 101 ++++++++++++++++++++++++++--------- srml/staking/src/phragmen.rs | 2 +- 2 files changed, 76 insertions(+), 27 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 0311fdf618c2e..f5f5f7a8f1d03 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -19,7 +19,11 @@ //! # Staking Module //! //! -//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharging their duties properly. +//! The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) +//! are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under +//! normal operation but are held at pain of "slash" (expropriation) should the staked maintainer be found not to be +//! discharging their duties properly. +//! You can start using the Staking module by implementing the staking [`Trait`]. //! //! ## Overview //! @@ -30,8 +34,8 @@ //! - Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. //! - Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. //! - Stash account: The account holding an owner's funds used for staking. -//! - Controller account: The account which controls am owner's funds for staking. -//! - Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. +//! - Controller account: The account which controls an owner's funds for staking. +//! - Era: A (whole) number of sessions, which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. //! - Slash: The punishment of a staker by reducing their funds ([reference](#references)). //! //! ### Goals @@ -46,23 +50,52 @@ //! //! #### Staking //! -//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. Henceforth, the former account that initiated the interest is called the **controller** and the latter, holding the funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account pair_, one of which to take the role of the controller and one to be the frozen stash account (any value locked in stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via the `bond()` function. +//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as +//! being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. +//! Henceforth, the former account that initiated the interest is called the **controller** and the latter, holding the +//! funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account +//! pair_, one to take the role of the controller and one to be the frozen stash account (any value locked in +//! stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via +//! the `bond()` function. //! -//! Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. +//! Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or +//! simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible +//! for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. //! //! #### Validating //! -//! A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of the network in other words. A validator should avoid both any sort of malicious misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of election is determined by nominators and their votes. An account can become a validator via the `validate()` call. +//! A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of +//! the network. A validator should avoid both any sort of malicious misbehavior and going offline. +//! Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they +//! are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of the +//! election is determined by nominators and their votes. An account can become a validator via the `validate()` call. //! //! #### Nomination //! -//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that their votes will be taken into account at the next election round. As mentioned above, a nominator must also place some fund in a stash account, essentially indicating the _weight_ of their vote. In some sense, the nominator bets on the honesty of a set of validators by voting for them, with the goal of having a share of the reward granted to them. Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply because the nominators will also lose funds if they vote poorly. An account can become a nominator via the `nominate()` call. +//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators +//! to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that its +//! votes will be taken into account at the next election round. As mentioned above, a nominator must also place some +//! funds in a stash account, essentially indicating the _weight_ of its vote. In some sense, the nominator bets on the +//! honesty of a set of validators by voting for them, with the goal of having a share of the reward granted to them. +//! Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The +//! same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. +//! This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply +//! because the nominators will also lose funds if they vote poorly. An account can become a nominator via the +//! `nominate()` call. //! //! #### Rewards and Slash //! -//! The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once a misbehavior is reported. One such misbehavior is a validator to be detected as offline more than a certain number of times. Once slashing is determined, a value is deducted from the balance of validator and all the nominators who voted for this validator. Same rules apply to the rewards in the sense of being shared among validator and its associated nominators. +//! The **reward and slashing** procedure are the core of the staking module, attempting to _embrace valid behavior_ +//! while _punishing any misbehavior or lack of availability_. Slashing can occur at any point in time, once +//! misbehavior is reported. One such misbehavior is a validator being detected as offline more than a certain number of +//! times. Once slashing is determined, a value is deducted from the balance of the validator and all the nominators who +//! voted for this validator. Same rules apply to the rewards in the sense of being shared among a validator and its +//! associated nominators. //! -//! Finally, any of the roles above can choose to temporarily step back and just chill for a while. This means that if they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can step back via the `chill()` call. +//! Finally, any of the roles above can choose to step back temporarily and just chill for a while. This means that if +//! they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer +//! be a candidate for the next election (again, both effects apply at the beginning of the next era). An account can +//! step back via the `chill()` call. //! //! ## Interface //! @@ -72,12 +105,14 @@ //! //! ### Dispatchable //! -//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and change their role, alongside some helper functions to get/set the metadata of the module. +//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and change their +//! role, alongside some helper functions to get/set the metadata of the module. //! //! Please refer to the [`Call`] enum and its associated variants for a detailed list of dispatchable functions. //! //! ### Public -//! The staking module contains many public storage items and (im)mutable functions. Please refer to the [struct list](#structs) below and the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. +//! The staking module contains many public storage items and (im)mutable functions. Please refer to the [struct list](#structs) +//! below and the [`Module`](https://crates.parity.io/srml_staking/struct.Module.html) struct definition for more details. //! //! ## Usage //! @@ -94,7 +129,7 @@ //! Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); //! ``` //! -//! To state desire in becoming a validator: +//! To state desire to become a validator: //! //! ```rust,ignore //! // controller account 4 states desire for validation with the given preferences. @@ -120,14 +155,21 @@ //! //! ### Slot Stake //! -//! The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, containing the _minimum value at stake among all validators._ +//! The term `slot_stake` will be used throughout this section. It refers to a value calculated at the end of each era, +//! containing the _minimum value at stake among all validators._ //! //! ### Reward Calculation //! -//! - Rewards are recorded **per-session** and paid **per-era**. The value of reward for each session is calculated at the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration storage named `SessionReward`. +//! - Rewards are recorded **per-session** and paid **per-era**. The value of the reward for each session is calculated at +//! the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of +//! the new _per-session-reward_ is calculated at the end of each era by multiplying `slot_stake` and a configuration +//! storage item named `SessionReward`. //! - Once a new era is triggered, rewards are paid to the validators and the associated nominators. -//! - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all of the nominators who had a vote for this validator, proportional to their staked value. -//! - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage (see `set_payee()`), to be one of the following: +//! - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at +//! each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. +//! The remaining portion is split among the validator and all of the nominators who had a vote for this validator, +//! proportional to their staked value. +//! - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage item (see `set_payee()`), to be one of the following: //! - Controller account. //! - Stash account, not increasing the staked value. //! - Stash account, also increasing the staked value. @@ -135,27 +177,33 @@ //! ### Slashing details //! //! - A validator can be _reported_ to be offline at any point via `on_offline_validator` public function. -//! - Each validator declares how many times they can be _reported_ before it actually gets slashed via the `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces a `OfflineSlashGrace`, which applies to all validators and prevents them from getting immediately slashed. -//! - Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a configuration storage item, `OfflineSlash`. -//! - Once a validator has been reported a sufficient amount of times, the actual value that gets deducted from that validator, and every single nominator that voted for it is calculated by multiplying the result of the above point by `2.pow(unstake_threshold)`. -//! - If the previous overflow, then `slot_stake` is used. -//! - If the previous is more than what the validator/nominator has in stake, all of their stake is slashed (`.max(total_stake)` in other words). +//! - Each validator declares how many times it can be _reported_ before it actually gets slashed via the +//! `unstake_threshold` in `ValidatorPrefs`. On top of this, the module also introduces an `OfflineSlashGrace`, +//! which applies to all validators and prevents them from getting immediately slashed. +//! - Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a +//! configuration storage item, `OfflineSlash`. +//! - Once a validator has been reported a sufficient number of times, the actual value that gets deducted from that +//! validator, and every single nominator that voted for it is calculated by multiplying the result of the above point +//! by `2.pow(unstake_threshold)`. +//! - If the previous overflows, then `slot_stake` is used. +//! - If the previous is more than what the validator/nominator has in stake, all of its stake is slashed (`.max(total_stake)`). //! //! ### Additional Fund Management Operations //! //! Any funds already placed into stash can be the target of the following operations: //! -//! - The controller account can free an portion (or all) of the funds using the `unbond()` call. Note that the funds are not immediately accessible, instead, a duration denoted by `BondingDuration` number of eras must pass until the funds can be actually removed. -//! - To actually remove the funds, once the bonding duration is over, the `withdraw_unbonded()` can be used. +//! - The controller account can free a portion (or all) of the funds using the `unbond()` call. Note that the funds +//! are not immediately accessible, instead, a duration denoted by `BondingDuration` (in number of eras) must pass until the funds can actually be removed. +//! - To actually remove the funds, once the bonding duration is over, `withdraw_unbonded()` can be used. //! - As opposed to the above, additional funds can be added to the stash account via the `bond_extra()` transaction call. //! //! ### Election algorithm details. //! -//! Current election algorithm is implemented based on Phragmén. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). +//! The current election algorithm is implemented based on Phragmén. The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). //! //! ## GenesisConfig //! -//! See the [`GensisConfig`] for a list of attributed that can be provided. +//! See the [`GensisConfig`] for a list of attributes that can be provided. //! //! ## Related Modules //! @@ -460,6 +508,7 @@ decl_module! { /// Take the origin account as a stash and lock up `value` of its balance. `controller` will be the /// account that controls it. + /// /// The dispatch origin for this call must be _Signed_. fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination) { let stash = ensure_signed(origin)?; @@ -811,7 +860,7 @@ impl Module { /// Select a new validator set from the assembled stakers and their role preferences. /// - /// returns the new SlotStake value. + /// Returns the new SlotStake value. fn select_validators() -> BalanceOf { // Map of (would-be) validator account to amount of stake backing it. diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs index d67612755bc0d..6211557ad525a 100644 --- a/srml/staking/src/phragmen.rs +++ b/srml/staking/src/phragmen.rs @@ -69,7 +69,7 @@ pub struct Vote { /// /// Reference implementation: https://github.com/w3f/consensus /// -/// returns a vector of elected candidates +/// Returns a vector of elected candidates pub fn elect( get_rounds: FR, get_validators: FV, From aa4994ec306600a8b0a27eb8cd88ce687c1bb9a7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 15 Mar 2019 16:18:37 +0100 Subject: [PATCH 17/21] Clean up a lot of the misleading language. --- srml/staking/src/lib.rs | 56 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index f5f5f7a8f1d03..00c976a2b482c 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -50,17 +50,16 @@ //! //! #### Staking //! -//! Almost any interaction with the staking module requires at least one account to become **bonded**, also known as -//! being a **staker**. For this, all that it is needed is a secondary _**stash account**_ which will hold the staked funds. -//! Henceforth, the former account that initiated the interest is called the **controller** and the latter, holding the -//! funds, is named the **stash**. Also, note that this implies that entering the staking process requires an _account -//! pair_, one to take the role of the controller and one to be the frozen stash account (any value locked in -//! stash cannot be used, hence called _frozen_). This process in the public API is mostly referred to as _bonding_ via +//! Almost any interaction with the staking module requires a process of *bonding* (also known as +//! being a **staker**). To become *bonded* a fund-holding account known as the _**stash account**_, which holds some of all of the +//! funds that become frozen in place as part of the staking process, is paired with an active **controller** account which issues +//! instructions on how they shall be used. This process in the public API is mostly referred to as _bonding_ via //! the `bond()` function. //! -//! Any account pair successfully placed at stake can accept three possible roles, namely: `validate`, `nominate` or -//! simply `chill`. Note that during the process of accepting these roles, the _controller_ account is always responsible -//! for declaring interest and the _stash_ account stays untouched, without directly interacting in any operation. +//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` and `Idle`. There are +//! three corresponding instructions to change between roles, namely: `validate`, `nominate` and `chill`. Note that the +//! _controller_ account is always responsible +//! for declaring changes and the _stash_ account stays untouched, without directly interacting in any operation. //! //! #### Validating //! @@ -68,17 +67,16 @@ //! the network. A validator should avoid both any sort of malicious misbehavior and going offline. //! Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they //! are declared as a _candidate_ and they _might_ get elected at the _next **era**_ as a validator. The result of the -//! election is determined by nominators and their votes. An account can become a validator via the `validate()` call. +//! election is determined by nominators and their votes. An account can become a validator candidate via the `validate()` +//! call. //! //! #### Nomination //! //! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators -//! to be elected. Once interest in nomination is stated by an account, it takes effect _immediately_, meaning that its -//! votes will be taken into account at the next election round. As mentioned above, a nominator must also place some -//! funds in a stash account, essentially indicating the _weight_ of its vote. In some sense, the nominator bets on the -//! honesty of a set of validators by voting for them, with the goal of having a share of the reward granted to them. -//! Any rewards given to a validator is shared among that validator and all of the nominators that voted for it. The -//! same logic applies to the slash of a validator; if a validator misbehaves all of its nominators also get slashed. +//! to be elected. Once interest in nomination is stated by an account, it takes effect at the next election round. The +//! funds in the nominator's stash account indicate the _weight_ of its vote. In some sense, the nominator bets on the +//! honesty of a set of validators by voting for them, with the goal of having some share of the reward granted to them. +//! Both rewards and any punishment that a validator earns are shared between itself and its nominators. //! This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply //! because the nominators will also lose funds if they vote poorly. An account can become a nominator via the //! `nominate()` call. @@ -167,12 +165,12 @@ //! - Once a new era is triggered, rewards are paid to the validators and the associated nominators. //! - The validator can declare an amount, named `validator_payment`, that does not get shared with the nominators at //! each reward payout through their `ValidatorPrefs`. This value gets deducted from the total reward that can be paid. -//! The remaining portion is split among the validator and all of the nominators who had a vote for this validator, -//! proportional to their staked value. +//! The remaining portion is split among the validator and all of the nominators that nominated the validator, +//! proportional to the value staked behind this validator. //! - All entities who receive a reward have the option to choose their reward destination, through the `Payee` storage item (see `set_payee()`), to be one of the following: -//! - Controller account. -//! - Stash account, not increasing the staked value. -//! - Stash account, also increasing the staked value. +//! - Controller account. +//! - Stash account, not increasing the staked value. +//! - Stash account, also increasing the staked value. //! //! ### Slashing details //! @@ -182,20 +180,20 @@ //! which applies to all validators and prevents them from getting immediately slashed. //! - Similar to the reward value, the slash value is updated at the end of each era by multiplying `slot_stake` and a //! configuration storage item, `OfflineSlash`. -//! - Once a validator has been reported a sufficient number of times, the actual value that gets deducted from that -//! validator, and every single nominator that voted for it is calculated by multiplying the result of the above point -//! by `2.pow(unstake_threshold)`. -//! - If the previous overflows, then `slot_stake` is used. -//! - If the previous is more than what the validator/nominator has in stake, all of its stake is slashed (`.max(total_stake)`). +//! - Once a validator has been reported a sufficient number of times, the total value that gets deducted from that +//! validator and their nominators is calculated by multiplying the result of the above point +//! by `2.pow(unstake_threshold)`. This punishment is shared in the same manner as the rewards. +//! - If the previous overflows, then `slot_stake` is used. (NOTE: This should never happen in a correctly implemented, non-corrupted, well-configured system) +//! - All individual accounts' punishments are capped at their total stake. (NOTE: This cap should never comee into force in a correctly implemented, non-corrupted, well-configured system) //! //! ### Additional Fund Management Operations //! //! Any funds already placed into stash can be the target of the following operations: //! //! - The controller account can free a portion (or all) of the funds using the `unbond()` call. Note that the funds -//! are not immediately accessible, instead, a duration denoted by `BondingDuration` (in number of eras) must pass until the funds can actually be removed. -//! - To actually remove the funds, once the bonding duration is over, `withdraw_unbonded()` can be used. -//! - As opposed to the above, additional funds can be added to the stash account via the `bond_extra()` transaction call. +//! are not immediately accessible, instead, a duration denoted by `BondingDuration` (in number of eras) must pass until the funds can actually be removed. +//! - To preparee the funds for transfer away from the stash account, then `withdraw_unbonded()` must be used once the bonding duration is over. +//! - Additional funds that are placed in the stash account may be bonded with the `bond_extra()` transaction call. //! //! ### Election algorithm details. //! From 1fee935c4456e873a20c3f501d82d4c6a806750c Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 15 Mar 2019 17:40:44 +0100 Subject: [PATCH 18/21] Update srml/staking/src/lib.rs --- srml/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 00c976a2b482c..c3190cae99306 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -184,7 +184,7 @@ //! validator and their nominators is calculated by multiplying the result of the above point //! by `2.pow(unstake_threshold)`. This punishment is shared in the same manner as the rewards. //! - If the previous overflows, then `slot_stake` is used. (NOTE: This should never happen in a correctly implemented, non-corrupted, well-configured system) -//! - All individual accounts' punishments are capped at their total stake. (NOTE: This cap should never comee into force in a correctly implemented, non-corrupted, well-configured system) +//! - All individual accounts' punishments are capped at their total stake. (NOTE: This cap should never come into force in a correctly implemented, non-corrupted, well-configured system) //! //! ### Additional Fund Management Operations //! From 1848306842546649f7ee072dcf872030c120a298 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 15 Mar 2019 17:40:51 +0100 Subject: [PATCH 19/21] Update srml/staking/src/lib.rs --- srml/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index c3190cae99306..b45c1c6ea8e94 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -192,7 +192,7 @@ //! //! - The controller account can free a portion (or all) of the funds using the `unbond()` call. Note that the funds //! are not immediately accessible, instead, a duration denoted by `BondingDuration` (in number of eras) must pass until the funds can actually be removed. -//! - To preparee the funds for transfer away from the stash account, then `withdraw_unbonded()` must be used once the bonding duration is over. +//! - To prepare the funds for transfer away from the stash account, then `withdraw_unbonded()` must be used once the bonding duration is over. //! - Additional funds that are placed in the stash account may be bonded with the `bond_extra()` transaction call. //! //! ### Election algorithm details. From 117eb93b871a9e012d0bb48a20b34d09d6073b91 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 15 Mar 2019 17:44:10 +0100 Subject: [PATCH 20/21] Update srml/staking/src/lib.rs --- srml/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index b45c1c6ea8e94..f005b3644a2c1 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -201,7 +201,7 @@ //! //! ## GenesisConfig //! -//! See the [`GensisConfig`] for a list of attributes that can be provided. +//! See the [`GenesisConfig`] for a list of attributes that can be provided. //! //! ## Related Modules //! From f9144b2b3e543a0f93ca5229cdc4598929b57d65 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 15 Mar 2019 22:43:57 +0100 Subject: [PATCH 21/21] Final fixes --- srml/staking/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index f005b3644a2c1..3751a14e3c6c2 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -24,6 +24,7 @@ //! normal operation but are held at pain of "slash" (expropriation) should the staked maintainer be found not to be //! discharging their duties properly. //! You can start using the Staking module by implementing the staking [`Trait`]. +//! The supported dispatchable functions are documented as part of the [`Call`] enum. //! //! ## Overview //! @@ -97,10 +98,6 @@ //! //! ## Interface //! -//! ### Types -//! -//! - `Currency`: Used as the measurement means of staking and funds management. -//! //! ### Dispatchable //! //! The Dispatchable functions of the staking module enable the steps needed for entities to accept and change their