From b9b541441b4404fa61a75ed9c0eecc44919b3542 Mon Sep 17 00:00:00 2001 From: Rob Walker Date: Tue, 28 May 2019 16:01:53 -0700 Subject: [PATCH] update book with passive staking (#4451) (#4455) * update book with passive staking (#4451) * undelete votestate etc --- book/makefile | 7 +- book/src/SUMMARY.md | 4 +- book/src/stake-delegation-and-rewards.md | 213 ++++++++++++++++++----- book/src/staking-rewards.md | 10 +- 4 files changed, 183 insertions(+), 51 deletions(-) diff --git a/book/makefile b/book/makefile index 14a5aeac2d..f0f31a5bf7 100644 --- a/book/makefile +++ b/book/makefile @@ -1,7 +1,8 @@ BOB_SRCS=$(wildcard art/*.bob) +MSC_SRCS=$(wildcard art/*.msc) MD_SRCS=$(wildcard src/*.md) -SVG_IMGS=$(BOB_SRCS:art/%.bob=src/img/%.svg) +SVG_IMGS=$(BOB_SRCS:art/%.bob=src/img/%.svg) $(MSC_SRCS:art/%.msc=src/img/%.svg) all: html/index.html @@ -17,6 +18,10 @@ src/img/%.svg: art/%.bob @mkdir -p $(@D) svgbob < $< > $@ + src/img/%.svg: art/%.msc + @mkdir -p $(@D) + mscgen -T svg -i $< -o $@ + src/%.md: %.md @mkdir -p $(@D) @cp $< $@ diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 14eed79af4..a8911b06c0 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -19,7 +19,7 @@ - [Data Plane Fanout](data-plane-fanout.md) - [Ledger Replication](ledger-replication.md) - [Secure Vote Signing](vote-signing.md) - - [Staking Delegation and Rewards](stake-delegation-and-rewards.md) + - [Stake Delegation and Rewards](stake-delegation-and-rewards.md) - [Performance Metrics](performance-metrics.md) - [Anatomy of a Validator](validator.md) @@ -39,7 +39,6 @@ - [Ledger Replication](ledger-replication-to-implement.md) - [Secure Vote Signing](vote-signing-to-implement.md) - [Staking Rewards](staking-rewards.md) - - [Passive Stake Delegation and Rewards](passive-stake-delegation-and-rewards.md) - [Cluster Economics](ed_overview.md) - [Validation-client Economics](ed_validation_client_economics.md) - [State-validation Protocol-based Rewards](ed_vce_state_validation_protocol_based_rewards.md) @@ -67,3 +66,4 @@ - [Reliable Vote Transmission](reliable-vote-transmission.md) - [Persistent Account Storage](persistent-account-storage.md) - [Cluster Software Installation and Updates](installer.md) + - [Passive Stake Delegation and Rewards](passive-stake-delegation-and-rewards.md) diff --git a/book/src/stake-delegation-and-rewards.md b/book/src/stake-delegation-and-rewards.md index 094a1b2294..a3d7734fb3 100644 --- a/book/src/stake-delegation-and-rewards.md +++ b/book/src/stake-delegation-and-rewards.md @@ -1,68 +1,195 @@ # Stake Delegation and Rewards -Stakers are rewarded for helping validate the ledger. They do it by delegating -their stake to fullnodes. Those fullnodes do the legwork and send votes to the -stakers' staking accounts. The rest of the cluster uses those stake-weighted -votes to select a block when forks arise. Both the fullnode and staker need -some economic incentive to play their part. The fullnode needs to be -compensated for its hardware and the staker needs to be compensated for risking -getting its stake slashed. The economics are covered in [staking +Stakers are rewarded for helping to validate the ledger. They do this by +delegating their stake to validator nodes. Those validators do the legwork of +replaying the ledger and send votes to a per-node vote account to which stakers +can delegate their stakes. The rest of the cluster uses those stake-weighted +votes to select a block when forks arise. Both the validator and staker need +some economic incentive to play their part. The validator needs to be +compensated for its hardware and the staker needs to be compensated for the risk +of getting its stake slashed. The economics are covered in [staking rewards](staking-rewards.md). This chapter, on the other hand, describes the underlying mechanics of its implementation. -## Vote and Rewards accounts +## Basic Besign -The rewards process is split into two on-chain programs. The Vote program -solves the problem of making stakes slashable. The Rewards account acts as -custodian of the rewards pool. It is responsible for paying out each staker -once the staker proves to the Rewards program that it participated in -validating the ledger. +The general idea is that the validator owns a Vote account. The Vote account +tracks validator votes, counts validator generated credits, and provides any +additional validator specific state. The Vote account is not aware of any +stakes delegated to it and has no staking weight. -The Vote account contains the following state information: +A separate Stake account (created by a staker) names a Vote account to which the +stake is delegated. Rewards generated are proportional to the amount of +lamports staked. The Stake account is owned by the staker only. Lamports +stored in this account are the stake. -* votes - The submitted votes. +## Passive Delegation -* `delegate_pubkey` - An identity that may operate with the weight of this - account's stake. It is typically the identity of a fullnode, but may be any -identity involved in stake-weighted computations. +Any number of Stake accounts can delegate to a single +Vote account without an interactive action from the identity controlling +the Vote account or submitting votes to the account. -* `authorized_voter_pubkey` - Only this identity is authorized to submit votes. +The total stake allocated to a Vote account can be calculated by the sum of +all the Stake accounts that have the Vote account pubkey as the +`StakeState::Delegate::voter_pubkey`. -* `credits` - The amount of unclaimed rewards. +## Vote and Stake accounts -* `root_slot` - The last slot to reach the full lockout commitment necessary - for rewards. +The rewards process is split into two on-chain programs. The Vote program solves +the problem of making stakes slashable. The Stake account acts as custodian of +the rewards pool, and provides passive delegation. The Stake program is +responsible for paying out each staker once the staker proves to the Stake +program that its delegate has participated in validating the ledger. -The Rewards program is stateless and pays out reward when a staker submits its -Vote account to the program. Claiming a reward requires a transaction that -includes the following instructions: +### VoteState -1. `RewardsInstruction::RedeemVoteCredits` -2. `VoteInstruction::ClearCredits` +VoteState is the current state of all the votes the validator has submitted to +the network. VoteState contains the following state information: -The Rewards program transfers lamports from the Rewards account to the Vote -account's public key. The Rewards program also ensures that the `ClearCredits` -instruction follows the `RedeemVoteCredits` instruction, such that a staker may -not claim rewards for the same work more than once. +* 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 Stake 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. This field can only modified by this identity. + +### 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 + +### VoteInstruction::Vote(Vec) + +* `account[0]` - RW - The VoteState + `VoteState::lockouts` and `VoteState::credits` are updated according to voting lockout rules see [Fork Selection](fork-selection.md) -### Delegating Stake +* `account[1]` - RO - A list of some N most recent slots and their hashes for the vote to be verified against. -`VoteInstruction::DelegateStake` allows the staker to choose a fullnode to -validate the ledger on its behalf. By being a delegate, the fullnode is -entitled to collect transaction fees when its is leader. The larger the stake, -the more often the fullnode will be able to collect those fees. -### Authorizing a Vote Signer +### StakeState + +A StakeState takes one of two forms, StakeState::Delegate and StakeState::MiningPool. + +### StakeState::Delegate + +StakeState is the current delegation preference of the **staker**. StakeState +contains the following state information: + +* Account::lamports - The staked lamports. + +* `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. + +### 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 +StakeState::MiningPool instances 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::Initialize + +* `account[0]` - RW - The StakeState::Delegate instance. + `StakeState::Delegate::credits_observed` is initialized to `VoteState::credits`. + `StakeState::Delegate::voter_pubkey` is initialized to `account[1]` + +* `account[1]` - R - The VoteState instance. + +### StakeInstruction::RedeemVoteCredits + +The Staker or the owner of the Stake account sends a transaction with this +instruction to claim rewards. + +The Vote account and the Stake account pair maintain a lifetime counter +of total rewards generated and claimed. When claiming rewards, the total lamports +deposited into the Stake account 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::Delegate instance that is redeeming votes +credits. +* `account[2]` - R - The VoteState instance, must be the same as +`StakeState::voter_pubkey` + +Reward is paid 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 Vote account token +balance, and the reward is deposited to the Stake account token balance. + +The total lamports paid is a percentage-rate of the lamports staked muiltplied by +the ratio of rewards being redeemed to rewards that could have been generated +during the rate period. + +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::Delegate::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. + +## Authorizing a Vote Signer `VoteInstruction::AuthorizeVoter` allows a staker to choose a signing service for its votes. That service is responsible for ensuring the vote won't cause the staker to be slashed. -## Limitations +## Benefits of the design -Many stakers may delegate their stakes to the same fullnode. The fullnode must -send a separate vote to each staking account. If there are far more stakers -than fullnodes, that's a lot of network traffic. An alternative design might -have fullnodes submit each vote to just one account and then have each staker -submit that account along with their own to collect its reward. +* 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. + +## Example Callflow + +Passive Staking Callflow diff --git a/book/src/staking-rewards.md b/book/src/staking-rewards.md index 404b10ad77..902d8481a9 100644 --- a/book/src/staking-rewards.md +++ b/book/src/staking-rewards.md @@ -1,8 +1,8 @@ # Staking Rewards -Initial Proof of Stake (PoS) (i.e. using in-protocol asset, SOL, to provide -secure consensus) design ideas outlined here. Solana will implement a proof of -stake reward/security scheme for node validators in the cluster. The purpose is +A Proof of Stake (PoS), (i.e. using in-protocol asset, SOL, to provide +secure consensus) design is outlined here. Solana implements a proof of +stake reward/security scheme for validator nodes in the cluster. The purpose is threefold: - Align validator incentives with that of the greater cluster through @@ -64,7 +64,7 @@ capital-at-risk to prevent a logical/optimal strategy of multiple chain voting. We intend to implement slashing rules which, if broken, result some amount of the offending validator's deposited stake to be removed from circulation. Given the ordering properties of the PoH data structure, we believe we can simplify -our slashing rules to the level of a voting lockout time assigned per vote. +our slashing rules to the level of a voting lockout time assigned per vote. I.e. Each vote has an associated lockout time (PoH duration) that represents a duration by any additional vote from that validator must be in a PoH that @@ -110,7 +110,7 @@ in a slashable amount as a function of either: 1. the fraction of validators, out of the total validator pool, that were also slashed during the same time period (ala Casper) 2. the amount of time since the vote was cast (e.g. a linearly increasing % of - total deposited as slashable amount over time), or both. + total deposited as slashable amount over time), or both. This is an area currently under exploration