Staking Miner
The staking-miner code is experimental and it is still in development phase. Use is at your own discretion, as there is a risk of losing some funds.
The staking miner is a passive validator functionality which runs when a new set of validators need to be elected for NPoS. This is a computationally intense process, hence the mining. Staking miners compete with each other to produce election solutions which consist of a validator set, stake distribution across that set, and a score indicating how optimal the solution is. Staking miners run the any given staking algortihms(as of now, sequential Phragmén or PhragMMS, this is subject to change if improved algorithms are introduced) to produce results, and the result is then sent as a transaction to the relay chain via a normal signed extrinsic. The transaction requires a bond, and a transaction fee. The best solution is rewarded which in the least covers the transaction fee, and the bond is returned to the account. If the solution is not valid, the bond and the fee are lost.
Staking miner uses a pallet called pallet_election_provider_multi_phase
and can only produce
solutions during the
SignedPhase
of the pallet's life cycle. Once the SignedPhase
is over and the
UnsignedPhase
starts, only the off-chain workers can provide election results.
Running the staking miner requires passing the seed of a funded account in order to pay the fees for the transactions that will be sent. The same account's balance is used to reserve deposits as well. The best solution in each round is rewarded. All correct solutions will get their bond back and the ones that submit invalid solutions will lose their bond.
NPoS election optimization
A basic election solution is a simple distribution of stake across validators, but this can be optimized for better distribution equaling a higher security score. The staking miner does not act as a validator and focuses solely on the election result and optimization of the solution. It connects to a specified chain and keeps listening to new signed phase of the election pallet in order to submit solutions to the NPoS election. When the correct time comes, it computes its solution and submits it to the chain. The default miner algorithm is sequential Phragmén with a configurable number of balancing iterations that improve the score.
Signed Phase of the election pallet
The election provider pallet pallet_election_provider_multi_phase
is divided into two phases,
signed and unsigned. At the end of the pallet's timeline, the function elect()
is called.
elect()
+ <--T::SignedPhase--> + <--T::UnsignedPhase--> +
+-------------------------------------------------------------------+
Phase::Off + Phase::Signed + Phase::Unsigned +
Solutions provided by the staking miner can only be submitted during the signed phase. Solutions are
submitted and queued on the chain as a RawSolution
. Once submitted, a solution cannot be retracted
by the originating account.
RawSolution
struct definition:
pub struct RawSolution<S> {
pub solution: S, // The solution itself
pub score: ElectionScore, // The claimed score of the solution.
pub round: u32, // The round at which this solution should be submitted.
}
A maximum of pallet::Config::MaxSignedSubmissions
will be stored on-chain and they will be sorted
based on score. Higher the score the more optimal the election solution is. On both Polkadot and
Kusama the
'MaxSignedSubmissions'
is set to {{ signed_max_submission }} submissions. This variable can be modified if needed through
governance.
Upon arrival of a new solution:
- If the queue is not full, it is stored in the appropriate sorted index.
- If the queue is full but the submitted solution is better than one of the queued ones, the worse solution is discarded, the bond of the outgoing solution is returned, and the new solution is stored in the correct index.
- If the queue is full and the solution is not an improvement compared to any of the queued ones, it is instantly rejected and no bond is reserved.
Upon the end of the signed phase, no more solutions can be submitted and the solutions in the queue
will be checked using
Pallet::feasibility_check
which ensures the score is indeed correct, and marks them as valid or invalid. By checking each
solution in the queue, the queue will be reorganized by score. The highest valid score will be
rewarded. Invalid solutions with higher score than the winning solution will be slashed. The rest of
the solutions will be discarded and their deposit will be returned.
Queue
+-------------------------------+
|Solution(score=20, valid=false)| +--> Slashed
+-------------------------------+
|Solution(score=15, valid=true )| +--> Rewarded, Saved
+-------------------------------+
|Solution(score=10, valid=true )| +--> Discarded
+-------------------------------+
|Solution(score=05, valid=false)| +--> Discarded
+-------------------------------+
| None |
+-------------------------------+
If you want to run a staking miner on your validator, refer to the repository provided in the resources section below.