Remove old accepted design proposals (#5951)
* remove passive-stake-delegation-and-rewards from summary * Delete passive-stake-delegation-and-rewards.md
This commit is contained in:
parent
31a276b628
commit
64f23ab26a
|
@ -84,7 +84,6 @@
|
||||||
- [Tower BFT](tower-bft.md)
|
- [Tower BFT](tower-bft.md)
|
||||||
- [Leader-to-Leader Transition](leader-leader-transition.md)
|
- [Leader-to-Leader Transition](leader-leader-transition.md)
|
||||||
- [Leader-to-Validator Transition](leader-validator-transition.md)
|
- [Leader-to-Validator Transition](leader-validator-transition.md)
|
||||||
- [Passive Stake Delegation and Rewards](passive-stake-delegation-and-rewards.md)
|
|
||||||
- [Persistent Account Storage](persistent-account-storage.md)
|
- [Persistent Account Storage](persistent-account-storage.md)
|
||||||
- [Reliable Vote Transmission](reliable-vote-transmission.md)
|
- [Reliable Vote Transmission](reliable-vote-transmission.md)
|
||||||
- [Repair Service](repair-service.md)
|
- [Repair Service](repair-service.md)
|
||||||
|
|
|
@ -1,216 +0,0 @@
|
||||||
# Stake Delegation and Reward
|
|
||||||
|
|
||||||
This design proposal focuses on the software architecture for the on-chain
|
|
||||||
voting and staking programs. Incentives for staking is covered in [staking
|
|
||||||
rewards](staking-rewards.md).
|
|
||||||
|
|
||||||
The current architecture requires a vote for each delegated stake from the
|
|
||||||
validator, and therefore does not scale to allow replicator clients to
|
|
||||||
automatically delegate their rewards.
|
|
||||||
|
|
||||||
The design proposes a new set of programs for voting and stake delegation, The
|
|
||||||
proposed programs allow many stake accounts to passively earn rewards with a
|
|
||||||
single validator vote without permission or active involvement from the
|
|
||||||
validator.
|
|
||||||
|
|
||||||
## Current Design Problems
|
|
||||||
|
|
||||||
In the current design each staker creates their own VoteState, and assigns a
|
|
||||||
**delegate** in the VoteState that can submit votes. Since the validator has to
|
|
||||||
actively vote for each stake delegated to it, validators can censor stakes by
|
|
||||||
not voting for them.
|
|
||||||
|
|
||||||
The number of votes is equal to the number of stakers, and not the number of
|
|
||||||
validators. Replicator clients are expected to delegate their replication
|
|
||||||
rewards as they are earned, and therefore the number of stakes is expected to be
|
|
||||||
large compared to the number of validators in a long running cluster.
|
|
||||||
|
|
||||||
## Proposed changes to the current design.
|
|
||||||
|
|
||||||
The general idea is that instead of the staker, the validator will own the
|
|
||||||
VoteState program. In this proposal the VoteState program is there to track
|
|
||||||
validator votes, count validator generated credits and to provide any
|
|
||||||
additional validator specific state. The VoteState program is not aware of any
|
|
||||||
stakes delegated to it, and has no staking weight.
|
|
||||||
|
|
||||||
The rewards generated are proportional to the amount of lamports staked. In
|
|
||||||
this proposal stake state is stored as part of the StakeState program. This
|
|
||||||
program is owned by the staker only. Lamports stored in this program are the
|
|
||||||
stake. Unlike the current design, this program contains a new field to indicate
|
|
||||||
which VoteState program the stake is delegated to.
|
|
||||||
|
|
||||||
### VoteState
|
|
||||||
|
|
||||||
VoteState is the current state of all the votes the **delegate** has submitted
|
|
||||||
to the bank. VoteState contains the following state information:
|
|
||||||
|
|
||||||
* votes - The submitted votes data structure.
|
|
||||||
|
|
||||||
* credits - The total number of rewards this vote program has generated over its
|
|
||||||
lifetime.
|
|
||||||
|
|
||||||
* root\_slot - The last slot to reach the full lockout commitment necessary for
|
|
||||||
rewards.
|
|
||||||
|
|
||||||
* commission - The commission taken by this VoteState for any rewards claimed by
|
|
||||||
staker's StakeState accounts. This is the percentage ceiling of the reward.
|
|
||||||
|
|
||||||
* Account::lamports - The accumulated lamports from the commission. These do not
|
|
||||||
count as stakes.
|
|
||||||
|
|
||||||
* `authorized_vote_signer` - Only this identity is authorized to submit votes, and
|
|
||||||
this field can only modified by this entity
|
|
||||||
|
|
||||||
### VoteInstruction::Initialize
|
|
||||||
|
|
||||||
* `account[0]` - RW - The VoteState
|
|
||||||
`VoteState::authorized_vote_signer` is initialized to `account[0]`
|
|
||||||
other VoteState members defaulted
|
|
||||||
|
|
||||||
### VoteInstruction::AuthorizeVoteSigner(Pubkey)
|
|
||||||
|
|
||||||
* `account[0]` - RW - The VoteState
|
|
||||||
`VoteState::authorized_vote_signer` is set to to `Pubkey`, instruction must by
|
|
||||||
signed by Pubkey
|
|
||||||
|
|
||||||
|
|
||||||
### StakeState
|
|
||||||
|
|
||||||
A StakeState takes one of two forms, StakeState::Stake and StakeState::MiningPool.
|
|
||||||
|
|
||||||
### StakeState::Stake
|
|
||||||
|
|
||||||
Stake is the current delegation preference of the **staker**. Stake
|
|
||||||
contains the following state information:
|
|
||||||
|
|
||||||
* `voter_pubkey` - The pubkey of the VoteState instance the lamports are
|
|
||||||
delegated to.
|
|
||||||
|
|
||||||
* `credits_observed` - The total credits claimed over the lifetime of the
|
|
||||||
program.
|
|
||||||
|
|
||||||
* `stake` - The actual activated stake.
|
|
||||||
|
|
||||||
* Account::lamports - Lamports available for staking, including any earned as rewards.
|
|
||||||
|
|
||||||
|
|
||||||
### StakeState::MiningPool
|
|
||||||
|
|
||||||
There are two approaches to the mining pool. The bank could allow the
|
|
||||||
StakeState program to bypass the token balance check, or a program representing
|
|
||||||
the mining pool could run on the network. To avoid a single network wide lock,
|
|
||||||
the pool can be split into several mining pools. This design focuses on using a
|
|
||||||
StakeState::MiningPool as the cluster wide mining pools.
|
|
||||||
|
|
||||||
* 256 StakeState::MiningPool are initialized, each with 1/256 number of mining pool
|
|
||||||
tokens stored as `Account::lamports`.
|
|
||||||
|
|
||||||
The stakes and the MiningPool are accounts that are owned by the same `Stake`
|
|
||||||
program.
|
|
||||||
|
|
||||||
### StakeInstruction::DelegateStake(stake)
|
|
||||||
|
|
||||||
* `account[0]` - RW - The StakeState::Stake instance.
|
|
||||||
`StakeState::Stake::credits_observed` is initialized to `VoteState::credits`.
|
|
||||||
`StakeState::Stake::voter_pubkey` is initialized to `account[1]`
|
|
||||||
`StakeState::Stake::stake` is initialized to `stake`, as long as it's less than account[0].lamports
|
|
||||||
|
|
||||||
* `account[1]` - R - The VoteState instance.
|
|
||||||
|
|
||||||
### StakeInstruction::RedeemVoteCredits
|
|
||||||
|
|
||||||
The VoteState program and the StakeState programs maintain a lifetime counter
|
|
||||||
of total rewards generated and claimed. Therefore an explicit `Clear`
|
|
||||||
instruction is not necessary. When claiming rewards, the total lamports
|
|
||||||
deposited into the StakeState and as validator commission is proportional to
|
|
||||||
`VoteState::credits - StakeState::credits_observed`.
|
|
||||||
|
|
||||||
|
|
||||||
* `account[0]` - RW - The StakeState::MiningPool instance that will fulfill the
|
|
||||||
reward.
|
|
||||||
* `account[1]` - RW - The StakeState::Stake instance that is redeeming votes
|
|
||||||
credits.
|
|
||||||
* `account[2]` - R - The VoteState instance, must be the same as
|
|
||||||
`StakeState::voter_pubkey`
|
|
||||||
|
|
||||||
Reward is payed out for the difference between `VoteState::credits` to
|
|
||||||
`StakeState::Delgate.credits_observed`, and `credits_observed` is updated to
|
|
||||||
`VoteState::credits`. The commission is deposited into the `VoteState` token
|
|
||||||
balance, and the reward is deposited to the `StakeState::Stake` token balance. The
|
|
||||||
reward and the commission is weighted by the `StakeState::lamports` divided by total lamports staked.
|
|
||||||
|
|
||||||
The Staker or the owner of the Stake program sends a transaction with this
|
|
||||||
instruction to claim the reward.
|
|
||||||
|
|
||||||
Any random MiningPool can be used to redeem the credits.
|
|
||||||
|
|
||||||
```rust,ignore
|
|
||||||
let credits_to_claim = vote_state.credits - stake_state.credits_observed;
|
|
||||||
stake_state.credits_observed = vote_state.credits;
|
|
||||||
```
|
|
||||||
|
|
||||||
`credits_to_claim` is used to compute the reward and commission, and
|
|
||||||
`StakeState::Stake::credits_observed` is updated to the latest
|
|
||||||
`VoteState::credits` value.
|
|
||||||
|
|
||||||
### Collecting network fees into the MiningPool
|
|
||||||
|
|
||||||
At the end of the block, before the bank is frozen, but after it processed all
|
|
||||||
the transactions for the block, a virtual instruction is executed to collect
|
|
||||||
the transaction fees.
|
|
||||||
|
|
||||||
* A portion of the fees are deposited into the leader's account.
|
|
||||||
* A portion of the fees are deposited into the smallest StakeState::MiningPool
|
|
||||||
account.
|
|
||||||
|
|
||||||
### Benefits
|
|
||||||
|
|
||||||
* Single vote for all the stakers.
|
|
||||||
|
|
||||||
* Clearing of the credit variable is not necessary for claiming rewards.
|
|
||||||
|
|
||||||
* Each delegated stake can claim its rewards independently.
|
|
||||||
|
|
||||||
* Commission for the work is deposited when a reward is claimed by the delegated
|
|
||||||
stake.
|
|
||||||
|
|
||||||
This proposal would benefit from the `read-only` accounts proposal to allow for
|
|
||||||
many rewards to be claimed concurrently.
|
|
||||||
|
|
||||||
## Passive Delegation
|
|
||||||
|
|
||||||
Any number of instances of StakeState::Stake programs can delegate to a single
|
|
||||||
VoteState program without an interactive action from the identity controlling
|
|
||||||
the VoteState program or submitting votes to the program.
|
|
||||||
|
|
||||||
The total stake allocated to a VoteState program can be calculated by the sum of
|
|
||||||
all the StakeState programs that have the VoteState pubkey as the
|
|
||||||
`StakeState::Stake::voter_pubkey`.
|
|
||||||
|
|
||||||
## Example Callflow
|
|
||||||
|
|
||||||
<img alt="Passive Staking Callflow" src="img/passive-staking-callflow.svg" class="center"/>
|
|
||||||
|
|
||||||
## Future work
|
|
||||||
|
|
||||||
Validators may want to split the stake delegated to them amongst many validator
|
|
||||||
nodes since stake is used as weight in the network control and data planes. One
|
|
||||||
way to implement this would be for the StakeState to delegate to a pool of
|
|
||||||
validators instead of a single one.
|
|
||||||
|
|
||||||
Instead of a single `vote_pubkey` and `credits_observed` entry in the StakeState
|
|
||||||
program, the program can be initialized with a vector of tuples.
|
|
||||||
|
|
||||||
```rust,ignore
|
|
||||||
Voter {
|
|
||||||
voter_pubkey: Pubkey,
|
|
||||||
credits_observed: u64,
|
|
||||||
weight: u8,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* voters: Vec<Voter> - Array of VoteState accounts that are voting rewards with
|
|
||||||
this stake.
|
|
||||||
|
|
||||||
A StakeState program would claim a fraction of the reward from each voter in
|
|
||||||
the `voters` array, and each voter would be delegated a fraction of the stake.
|
|
Loading…
Reference in New Issue