Demystifying Solana’s Stake State
Introduction
Rated’s mission of building “reputation for machines” across multiple networks has taken a new leap with launching support for Solana.
One of the most serious challenges we encountered in delivering this, was the scale and availability of data that Solana produces, particularly related to the actions and state of stake accounts. Stake accounts are accounts created by users in the process of delegating to a Solana validator, which are then used to interact with a specific validator for the lifetime of the account.
The crux of the challenge is that information about the past states of those accounts is not readily available; the only way to reconstruct it at a specific point in time is by putting together its component parts (i.e. the sequence of actions that amounted to state transitions).
Solana typically produces ~2,500 transactions per second, with ~216,000 slots/blocks per day. The stake program alone has produced over 19.5 million actions relevant to tracking the state of active stake accounts throughout the network's lifetime. The sheer amount of data required to rebuild the state, as well as the inconsistent and difficult to interpret staking instruction metadata, make the task anything but trivial.
This blog details our approach to calculating stake state on Solana, outstanding issues and open questions, and, importantly, how we plan to work with the community to build on this work.
Learn more about the Solana APIs that Rated offers via rated.network/apis and api-docs.rated.network
Stake State Calculation Methodology
Indexing Stake Actions
Our approach begins by indexing specific actions from Solana’s stake program. These include delegations, deactivations, merges, splits, and withdrawals, each impacting the stake state. We parse these actions into a standardised schema that captures their impact on the state of each stake account involved.
Datasets
Our calculation leverages three critical datasets, which are the result of our indexing and of the logic we have developed to calculate Solana’s stake state:
Previous Epoch Stake State: The state of stake accounts from the previous epoch, including their balances and the vote accounts of the validators they have delegated to.
Current Epoch Rewards: These rewards are distributed in the first slot of each epoch and must be added to the stake accounts' balances.
Stake Program Actions: Actions taken during the current epoch that affect stake state, specifically the validator’s vote account a stake account has delegated to, and the amount the stake account has delegated.
Processing Stake Actions
There are several challenges in calculating stake state. The most significant one is that the vote account of the validator a stake account has delegated to is not present in the metadata of every stake action. The second is that while there are explicit delegate and deactivate actions which take effect at the start of the following epoch, there are implicit activations and deactivations that take effect immediately through split and merge actions.
We developed an iterative approach to propagating this metadata across stake program actions through the use of a current vote_account field, and a pending vote_account_target field representing the vote_account value that would come into effect at the start of the following epoch. At a high level, the logic proceeds as follows.
Step 1: Initial Action Processing
We begin by processing the first actions for each stake account in the epoch, and joining these with the historic state. This helps in understanding the initial changes to each account. There are some exceptions to this, for example the receiver in delegate and split actions. For the former we know the vote_account from the action metadata, and for the latter we will propagate the vote_account from the sender.
Step 2: Vote Account Propagation
Since the vote_account is crucial yet not always present in action metadata, we meticulously associate and propagate this data to subsequent stake actions for a given stake account until we meet a condition that indicates the vote_account or vote_account_target has changed.
Step 3: Split Action Propagation
There is a special case in vote account propagation for split actions where vote account details from a sender are propagated to the receiver. We accomplish this through a join to propagate known vote_account and vote_account_target values.
Step 4: Iterative Propagation
We repeat steps two and three in a loop until there are no longer any null values for vote_account. The complexity here is in ensuring that we correctly handle edge cases like split actions in which the sender’s balance goes to zero. This indicates an implicit deactivated state which should be propagated to any of the account’s subsequent stake actions in the epoch, but at the same time, the receiver of the split inherits the original vote_account and vote_account_target of the sender.
Step 5 - Updated Stake State
Updated Stake State: Since we want the latest updated state for each account, we select the last action for each which should now have all relevant fields related to its state populated, and make some adjustments to the delegated_stake before coalescing the results with the previous epoch’s stake account state.
Challenges and Open Questions
Incomplete Metadata and Implicit Effects
The inconsistent availability of fields like vote_account in some stake actions was the most significant challenge we faced, as well the presence of implicit activations and deactivations. This required relatively complex logic, and extensive debugging to understand the many edge cases that appear on a high-volume blockchain like Solana.
Account Balances and Delegated Stake
In using Solana stake actions to calculate the state of stake accounts, we rely on the post_transaction_balance to understand the amount of delegated_stake for a particular account. However, this needs to be adjusted since the two values are not equal. Although an account must use its entire balance in the context of a delegate action, there is a rent-exempt reserve required for the account to be considered active by the protocol, and there are a variety of ways in which this un-staked balance can change over the lifecycle of a stake account.
We have accounted for the majority of these through calculating rent and incorporating withdraw actions, but one outstanding issue is arbitrary actions that increase the un-staked balance of an account. Currently, in order to account for these balance changes, we would need to index and parse all instructions affecting the balance of a stake account and incorporate them in the calculation logic, which is beyond the scope of our v0 product. The maximum difference we have observed in a validator’s stake due to this issue is 0.703% when comparing our results for an epoch to recent snapshots of stake account state shared by the Jito Foundation.
Conclusion and Forward Look
Rated's methodology not only clarifies the details of Solana's stake state implementation but also paves the way for community-driven improvements and innovations. By planning to open-source our methodologies and codebase, we aim to foster a collaborative environment where developers, and partners in the validator and delegator communities can build on and benefit from our contributions.
Some things we’re excited to see and contribute to are:
Delegation management: Efficiently managing stake delegations to maximise returns.
Rewards accounting and auditing: Ensuring accurate and transparent recording of rewards for validators and delegators.
Institutional rebates: Facilitating the calculation of rebates between operators and institutional delegators.
Tax purposes: Providing necessary data for tax computation related to staking rewards.
As we continue to iterate on this work, and on the products we’ve released that build on top of it, we invite the Solana community to engage with our tools and share their insights, helping us enhance the transparency and functionality of blockchain technology together.
Learn more about the Solana APIs that Rated offers via rated.network/apis and api-docs.rated.network