2023-02-03 14:32:08 -08:00
|
|
|
---
|
|
|
|
simd: '0022'
|
|
|
|
title: Multi Delegation Stake Account
|
|
|
|
authors:
|
|
|
|
- Jon Cinque (Solana Labs)
|
|
|
|
category: Standard
|
|
|
|
type: Core
|
|
|
|
status: Draft
|
|
|
|
created: 2023-01-20
|
|
|
|
feature: (fill in with feature tracking issues once accepted)
|
|
|
|
---
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
A new "multi stake" account that allows for multiple movements of stake, useful
|
|
|
|
for simpler stake movement through more activations, deactivations, or redelegation.
|
|
|
|
|
|
|
|
## New Terminology
|
|
|
|
|
|
|
|
* "multi stake": a stake account with multiple `Delegation` instances
|
2023-03-21 20:46:04 -07:00
|
|
|
* "small stake": a stake whose delegation is less than current minimum stake
|
|
|
|
delegation amount
|
2023-02-03 14:32:08 -08:00
|
|
|
|
|
|
|
## Motivation
|
|
|
|
|
|
|
|
Stake operations are cumbersome or impossible for many ordinary uses. For example,
|
|
|
|
delegating more lamports in an existing stake account requires creating a new
|
|
|
|
account, delegating, waiting, merging, then withdrawing the rent-exempt lamports.
|
|
|
|
|
|
|
|
The current stake `redelegate` instruction requires using a new stake account and
|
|
|
|
eventually cleaning up the old one, which can be tricky to use.
|
|
|
|
|
|
|
|
As a minimum stake delegation amount is applied to the network, and potentially
|
|
|
|
increased over time, these operations will become more complicated, since all
|
|
|
|
delegations must clear that threshold. Small SOL amounts will be left liquid rather
|
|
|
|
than delegated to a validator.
|
|
|
|
|
|
|
|
Additionally, stake pools always carry some risk or capital inefficiency for the
|
|
|
|
stake pool operator. Either there's a requirement to leave liquid SOL available
|
|
|
|
for small stakers to exit, or small stakes cannot enter because there's not enough
|
|
|
|
to cover the minimum delegation amount.
|
|
|
|
|
|
|
|
Small stakes need to be delegated, while not causing problems in the validator's
|
|
|
|
stakes cache.
|
|
|
|
|
|
|
|
For more background, here's an earlier proposal meant for only for redelegation:
|
|
|
|
https://github.com/solana-labs/solana/pull/24762
|
|
|
|
|
|
|
|
## Alternatives Considered
|
|
|
|
|
|
|
|
The easiest solution is to change the validator's stakes cache, since that only
|
|
|
|
impacts the specific implementation in the Solana Labs validator.
|
|
|
|
|
|
|
|
In the perfect situation, small stakes are properly delegated, but don't receive
|
|
|
|
rewards. Meaning:
|
|
|
|
|
|
|
|
* they don't take up space in the stakes cache
|
|
|
|
* they take the correct amount of epoch boundaries to activate / deactivate
|
|
|
|
* they are included in a validator's voting power
|
|
|
|
|
|
|
|
There are a few ways of solving this at the stakes cache level, and they all have
|
|
|
|
serious issues.
|
|
|
|
|
|
|
|
* Include small stakes in the cache, but don't pay out rewards
|
|
|
|
|
|
|
|
This is the simplest solution, which essentially imposes a "minimum reward earning
|
|
|
|
amount". So you can delegate small stakes, but they won't earn rewards.
|
|
|
|
|
|
|
|
Unfortunately, small stakes can still bloat the stakes cache from a memory level.
|
|
|
|
|
|
|
|
* Don't include small stakes in the cache, but track them in transactions
|
|
|
|
|
2023-03-21 20:46:04 -07:00
|
|
|
In this solution, on every transaction that manipulates a small stake
|
|
|
|
delegation, it includes its delegation amount in the validator's voting power,
|
|
|
|
but doesn't add its pubkey and `Delegation` to the cache.
|
2023-02-03 14:32:08 -08:00
|
|
|
|
|
|
|
The runtime tracks the pre and post state of every account, and for a successful
|
|
|
|
transaction, subtracts the old small stake delegation amount, and adds the new small
|
|
|
|
stake delegation amount.
|
|
|
|
|
|
|
|
During rewards payout, small stakes are completely omitted, since they are not
|
|
|
|
present in the cache.
|
|
|
|
|
|
|
|
This is incredibly brittle, however, and introduces more overhead in the runtime.
|
2023-03-21 20:46:04 -07:00
|
|
|
The bank must hold onto pre-states for all transactions to debit the stakes
|
|
|
|
cache. And, if called from the outside, all `store_accounts` functions on the
|
|
|
|
bank could easily invalidate the stakes cache.
|
2023-02-03 14:32:08 -08:00
|
|
|
|
|
|
|
For example, if you store a small stake directly, what does the cache do? What
|
|
|
|
was the pre-state of that small stake? There's no way to know.
|
|
|
|
|
|
|
|
## Detailed Design
|
|
|
|
|
|
|
|
Rather than hacking the validator, let's change the stake program.
|
|
|
|
|
|
|
|
With a new "multi delegation stake" account, carrying *two* `Delegation` instances,
|
|
|
|
the stake program becomes much more flexible.
|
|
|
|
|
|
|
|
Here are some example uses:
|
|
|
|
|
|
|
|
### Add or remove small stake
|
|
|
|
|
|
|
|
To add a small stake to your account, transfer the lamports, call `delegate` once
|
|
|
|
more, and now your stake account has two delegations: the initial one, and the
|
|
|
|
newly activating one.
|
|
|
|
|
|
|
|
Once the new `Delegation` is active, an `update` instruction follows
|
|
|
|
the existing `merge` logic to consolidate the two `Delegation`s into one.
|
|
|
|
|
|
|
|
The same roughly applies for removing a small stake. You `deactivate` a portion
|
|
|
|
of it, which adds another delegation to your stake account: the initial one, and
|
|
|
|
the newly deactivating one.
|
|
|
|
|
|
|
|
### Redelegate
|
|
|
|
|
|
|
|
With another `Delegation` instance, you can redelegate from one validator to another
|
|
|
|
within the same account.
|
|
|
|
|
|
|
|
It works the same as the existing "redelegate" instruction, except the lamports
|
|
|
|
all stay in the same account, and the second `Delegation` covers the redelegation.
|
|
|
|
|
|
|
|
The `update` instruction clears out the first one once it's inactive.
|
|
|
|
|
|
|
|
### Upgrade
|
|
|
|
|
|
|
|
The stake program exposes a new instruction to upgrade a stake account to a multi-stake
|
|
|
|
account. It performs a realloc to the new size of the stake account, and
|
|
|
|
updates the rent-exempt reserve field in the stake account `Meta`.
|
|
|
|
|
|
|
|
It must be signed by the current staker or withdrawer, and takes an optional
|
|
|
|
payer to fund the additional rent-exempt reserve requirement.
|
|
|
|
|
|
|
|
### Runtime
|
|
|
|
|
|
|
|
The main difference to the runtime is processing up to two `Delegation`s
|
|
|
|
per account.
|
|
|
|
|
|
|
|
There's minor impact on the stakes cache, which gets a little bigger for the
|
|
|
|
additional `Delegation` instances.
|
|
|
|
|
|
|
|
There's minor impact on rewards payout, since the time spent calculating the rewards
|
|
|
|
amount is negligible compared to the time spent storing the accounts. The number
|
|
|
|
of account storages stays the same.
|
|
|
|
|
|
|
|
## Impact
|
|
|
|
|
|
|
|
Validators likely see a small increase in memory usage from additional `Delegation`
|
|
|
|
entries in the stakes cache, and perhaps a tiny increase in rewards payout time,
|
|
|
|
but nothing substantial.
|
|
|
|
|
|
|
|
Dapp developers have to deal with a new stake account type. This may break programs
|
|
|
|
that try to deserialize any stake account.
|
|
|
|
|
|
|
|
The network benefits as a whole:
|
|
|
|
|
2023-03-21 20:46:04 -07:00
|
|
|
* stake accounts are more flexible for adding or removing stake, without splits
|
|
|
|
and merges
|
2023-02-03 14:32:08 -08:00
|
|
|
* stakers can easily redelegate without missing out on rewards
|
|
|
|
|
|
|
|
## Security Considerations
|
|
|
|
|
|
|
|
It's risky to change the runtime, especially the stake program and rewards payout.
|
|
|
|
Thankfully, since this all operates on the level of the `Delegation`, as long
|
|
|
|
as we pass all the instances as needed, none of the most sensitive parts need
|
|
|
|
to change.
|
|
|
|
|
|
|
|
## Backwards Compatibility *(Optional)*
|
|
|
|
|
|
|
|
While existing programs that create and use their own stake accounts are not impacted,
|
|
|
|
those that accept any stake account will crash on multi-stakes. There's no way
|
|
|
|
around that, since the proposal entails a new stake account variant.
|
|
|
|
|
|
|
|
## Appendix: Single validator stake pool
|
|
|
|
|
|
|
|
A single-validator stake pool program can manage small stakes with 100% efficiency
|
|
|
|
using "multi stakes".
|
|
|
|
|
|
|
|
With a total of *two* `Delegation` instances, the program can add or remove small
|
|
|
|
stakes. One instance covers the main amount, and the other covers new activations
|
|
|
|
or deactivations.
|
|
|
|
|
|
|
|
For small stake deposit, you simply transfer the lamports and activate the new amount.
|
|
|
|
|
|
|
|
If a user wishes to withdraw, the program first withdraws from the activating amount.
|
|
|
|
If there is no more activating amount available, then the pool deactivates from
|
2023-03-21 20:46:04 -07:00
|
|
|
the main delegation and provides a ticket to the user, used to claim their lamports
|
|
|
|
after deactivation.
|