wtf is StakeNet?
An introduction to StakeNet, what it does today, and what it could do in the future
Note: This article is my own opinion and doesn’t represent that of any entity I may or may not be associated with. None of the following should be interpreted as financial, investment, legal, tax, relationship, or any other type of advice.
StakeNet is a new primitive for Solana that allows one to build autonomous, decentralized programs that allocate resources across a network of node operators.
StakeNet was originally designed for Solana liquid staking protocols. Today, every Solana liquid staking protocol uses a hot wallet to control their delegation strategy, which brings a slew of centralization risks that become increasingly concerning as the total amount of LSTs on Solana increases. In order for liquid staking to truly scale, this hot wallet needs to be decentralized. StakeNet was built to do this.
In addition to running stake pools, I think there’s an application for StakeNet in other decentralized, high performance, and autonomous networks. This can be things like restaking protocols, liquid restaking networks, oracle networks, and more. In this article, I’ll cover why StakeNet was created, what it can do today, some cool things people could build, and where I think StakeNet could head in the future.
Why StakeNet?
Despite the promise of increasing decentralization, today all Solana stake pools are centralized.
Solana stake pools require consistent updating; in the SPL Stake Pool Program, this permission is delegated to the staker authority. The staker has a basic functions:
Today, the staker is typically a hot wallet that an off-chain bot uses to control stake movement. The simplest version of this bot delegates new stake to a small set of validators and doesn’t rebalance. In the most complex case, this bot collects data to a database, has a hosted API for monitoring the data, and constantly adjusts the pool by adding and removing validators based on their performance, decentralization, and other criteria.
When liquid staking grows to significant portions of the network, that keypair is an extreme centralization risk. In the worst case, the server gets hacked and there’s a large stake movement to malicious validators. In another case, the team sunsets their product and users are left with a non-functional liquid staking token.
StakeNet was designed so this authority can be delegated to a program, instead of a hot wallet. This puts all delegation logic on-chain, which means a previously trusted and opaque system can be transitioned to a trustless and transparent one.
StakeNet Technical Details
StakeNet is a closed-loop control system. Similar to a robot, it does a repeated loop of sense, compute, actuate. It leverages a set of on-chain programs and off-chain keepers to sense the stake pools performance, compute the scores associated with each validator and actuate the stake pool by moving stake.
The Validator History Program
In order to build an efficient staking network, you need data. StakeNet uses the Validator History Program, deployed at HistoryJTGbKQD2mRgLZ3XhqHnN811Qpez8X9kCcGHoa, to collect data. Every validator on Solana has a ValidatorHistory account deployed to a deterministic addresses. The validator history account contains a 512 item circular buffer, one entry for each epoch. There are around 150 epochs per year, meaning roughly three years of validator data can be stored on-chain. An example of what this circular buffer looks like in memory is below, with each epoch labeled:
As the epochs progress, the index pointer rotates in a clockwise fashion. When it reaches a spot that already has data, it overwrites it.
Each index in the circular buffer contains a ValidatorHistoryEntry. The important fields are below:
pub struct ValidatorHistoryEntry {
pub activated_stake_lamports: u64,
pub epoch: u16,
pub mev_commission: u16,
pub epoch_credits: u32,
pub commission: u8,
pub client_type: u8,
pub version: ClientVersion,
pub ip: [u8; 4],
pub is_superminority: u8,
pub rank: u32,
pub vote_account_last_update_slot: u64,
...
}
On Solana, the most important consensus data lives inside the runtime under a validator’s VoteAccount. The VoteAccount layout looks like the following:
pub struct VoteState {
pub node_pubkey: Pubkey,
pub authorized_withdrawer: Pubkey,
pub commission: u8,
pub votes: VecDeque<LandedVote>,
pub epoch_credits: Vec<(Epoch, u64, u64)>,
pub last_timestamp: BlockTimestamp,
...
}
Solana’s consensus data can be access in any on-chain program which compared to Ethereum’s separate consensus and execution layers, is extremely useful for StakeNet. To update the consensus state, keepers send a periodic instruction which tells the program to copy data from the VoteAccount to the ValidatorHistory account. An example transaction that does this is here.
Some of the information required in the ValidatorHistoryEntry isn’t available on-chain, so there’s a set of other instructions that handle off-chain data upload. For instance, the validator’s client type (Solana Labs, Jito-Solana, Firedancer, etc.), client version (v1.16.15, v1.17.11-jito, …), and the validator’s IP address. While this information isn’t available on-chain, every validator participates in a gossip network, sharing and forwarding the information of validators on the network. A useful property of the gossip network is that all information is signed by validators, which means data can be cryptographically verified and associated with a specific validator.
One piece of data validators share in the gossip network is the CrdsValue, which contains a signed payload containing information packed into a CrdsData enumeration. This payload contains a few different fields like the contact information (what services are hosted on a given IP:port), snapshot slots, software version, and more.
StakeNet keepers listen for this data on gossip and upload the signed payload on-chain. By leveraging the built-in Ed25519 Program, the transaction contains an instruction that verifies the signature of the gossip payload and then uses instruction introspection to ensure the signature was validated before parsing the signed payload and storing the necessary fields in the ValidatorHistoryEntry. By leveraging the signed gossip data from a given validator, the program can cryptographically guarantee the validator produced the data and that the data in the Validator History program can be trusted. An example of a transaction that uploads the gossip data is here.
The rank, superminority, and activated stake needs to be collected and aggregated off-chain using an RPC node. Currently this data is uploaded by a trusted keeper. There are likely to be more fields like this. In the future, StakeNet can leverage decentralization and economic security to aggregate this data from multiple cranks.
The Steward
The Steward Program is the compute and actuation piece of StakeNet. The Steward program allows the stake pool to adapt to changes on a network, such as validators shutting down, poor validator performance, and even geographic centralization.
The Steward Program takes over the staker authority of a stake pool, which is responsible for managing the delegation of Solana to a network of validators. The Steward program runs a state machine which:
periodically calculates scores on validators based on data stored in the Validator History Program.
determines each validator’s allocated pro-rata share of stake in the pool
handles the delegation of stake determined by each validator’s pro-rata share of the pool
The Steward program has several configuration parameters can be directly controlled by governance. For parameter tuning, the delegation power of stake pool is directly in the hands of community governance and the keepers that power the network. This minimizes human intervention on a day-to-day basis.
When new delegation logic is written, the staker authority can be transferred to a new program by governance. Keepers also participate in running this program, closely coordinating with keeping the Validator History program updated before re-calculating scores.
An Example Delegation State Machine
To give readers a concrete idea of a liquid staking delegation state machine, I’ve included a first pass at one below.
The delegation system starts by computing the score for every validator in the validator set. As an example scoring mechanism which leverages the Validator History Program:
MEV Commission:
Look back 10 epochs. If MEV commission > 10%, final score is 0.
Jito-Solana
Look back 10 epochs. If no MEV commission was set, final score is 0.
Epoch Credits (voting score)
Look back 20 epochs and find the average epoch credits per epoch.
In addition, look to see if any excessive delinquency. If excessive deliquency, final score is 0.
Skip Rate (failed to produce a block at a given slot)
Look back 20 epochs and find the average skip rate per epoch
Commission
If any commission rug pulls in the entire history, final score is 0.
Superminority
If in the superminority, the score is 0.
Final score:
mev_commission_score
* superminority_score
* delinquency_score
* running_jito_score
* (average_vote_credits / average_blocks)
* (1. - commission)
After the scores have been computed, the delegation selection process can run. The delegation selection process decides what validators are in the stake pool based on the score calculated for them. To keep things simple, one could delegate an equal amount to the top 100 or 200 validators in the pool by score. Something more complex could select a validator set size (200 validators) and decide to delegate stake pro-rata to each validator based on their score.
After this, there’s a few states, which the first implementation can pass through and go through to Unstake. Unstake looks at the desired state of the delegations and compare to the actual. Any validators that have excess stake according to the delegation pro-rata computed above lose the stake.
The state machine then go to delegate reserves. Any new SOL the stake pool receives or any SOL that has been undelegated from validators goes to the reserve account. The DelegateReserves looks at the reserves, each validator’s current pro-rata share of the pool, and the desired pro-rata share and delegates stake to validators that need more. Afterwards, the state machine goes back to idle.
Every epoch, the state machine re-computes scores to determine if any validators deserve to be instantly unstaked. It then update the delegations based on that, potentially removing that validator from the set and distributing it’s pro-rata share among all the other validators in the set. Another unstake process is run from that validator, then the state machine goes back to idle.
The ComputeScoresForUnstake, ComputeNewDelegations, Unstake, DelegateReserves loop happens every epoch for 10 epochs. At the end of 10 epochs, the process starts over, where the scores are recomputed for the entire set, a new set is selected, and any balancing happens before maintaining the pool on that set. Recalculating a new validator set every 10 epochs strikes a balance between keeping the pool high performance and not churning stake between operators too much, which could drag yield.
Future Work for the StakeNet Liquid Staking
The most interesting and under explored field is the validator’s IP address, which brings the validator into the physical world. For instance, one can find a validator’s latitude and longitude from their IP by using a service like ipinfo, Maxmind, and others. One can also find their ASN, data center, the path between nodes in a network using traceroute, and more. These qualities are very important for network decentralization. Most of this information relies on centralized parties and I look forward to the community thinking about bringing this information on-chain in a decentralized process.
Some other interesting StakeNet ideas, some of which might be nerd snipes:
Platform-ize the Steward program with plugins
How can the Steward program be turned into a platform that makes it easier for others to integrate?
Can you build plugins that allow for easy customization of a delegation strategy? For instance, can you split stake pools into a few different pieces with different delegation strategies?
Stake-weighted delegation strategies based on how many governance tokens users stake to a strategy
For instance, imagine a stake pool contains several delegation strategies running at the same time. The percent of the total Solana stake in the stake pool that a specific strategy receives is pro-rata to all governance tokens staked to the currently running strategies.
Competitions to optimize the performance of a stake pool
Users can compete to build better delegation algorithms using historical StakeNet data.
Users can suggest a new algorithm with data showing it’s performance overtime and an implementation that a stake pool should upgrade to.
The best performing delegation strategy can receive emissions and/or a percentage of the stake pool’s fees until a better algorithm is found.
Allow users to easily customize delegation for stake accounts
For instance, only delegate my stake account to Jito-Solana validators with less than 1M SOL based out of Asia and South America.
One click stake pool setup and management
There could be a UI that allows anyone to set up a fully automated stake pool with some easy to adjust logic. This could be useful for NFT projects and communities that want to set up LSTs on Solana.
Track the block quality of validators and use it to influence delegation criteria
How does one quantify if validators are making “good” or “bad” blocks?
Can you quantify this and store it in StakeNet?
Bridging StakeNet data to other networks
Other networks could leverage Solana’s cheap storage and compute to collect and coordinate delegation criteria for other proof of stake networks.
Future StakeNet Applications
I’m confident that other stake pools on Solana will take an interest in StakeNet and start to build on top of it. This can be as simple as LSTs with small validator sets to something much more complex.
Over the last few weeks, I’ve been thinking a lot about StakeNet. I think the core building blocks of StakeNet will get used in other protocols that have similar problems as liquid staking. This includes restaking networks, liquid restaking protocols, oracle networks, and more. At scale, all of these systems need to intelligently and autonomously allocate assets across a decentralized network of actively validated services and high performance node operators. If all delegation adjustments must be performed by governance, these protocols will be slow to respond to evolving node operators. They may turn to off-chain automation to do this, but that brings a level of centralization. Running delegation strategies for something like a liquid restaking protocol using something similar StakeNet gives you the best of both worlds - automation and governance to intervene for fine tuning or emergency intervention.
In the end, all roads lead back to StakeNet.
If you found this article interesting, please share it below! Follow me on twitter @buffalu__ and let me know what else you’d like me to write about.