-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: introduce PrecommitProcessors to the StateManager #257
base: testnet-slashing
Are you sure you want to change the base?
Conversation
Rewards v2.1 state models
# Motivation We need to support Rewards v2.1 calculation. This PR builds on top of #197 which supported the Eigen state models for `OperatorDirectedOperatorSetRewardSubmissions`, `OperatorSetSplits`, `OperatorSetOperatorRegistrations`, `OperatorSetStrategyRegistrations`. # Modifications * Snapshot generation for: `OperatorDirectedOperatorSetRewardSubmissions`, `OperatorSetSplits`, `OperatorSetOperatorRegistrations`, `OperatorSetStrategyRegistrations`. * Refactoring Staging and Final numbering from 11 and 12 to 15 and 16. * Mississippi hard fork for Rewards v2.1. * New Operator Directed Operator Set rewards calculation to be triggered after Mississippi hard fork. * Updated Rewards For All Earners (Programmatic Incentives) calculation to include operators registered to operator sets after Mississippi hard fork. * Staker-operator calculation for Rewards v2.1. # Results Rewards v2.1 calculation. # Tests Existing Rewards tests passing. <img width="660" alt="Screenshot 2025-01-31 at 1 33 38 PM" src="https://github.com/user-attachments/assets/876c2d7c-be22-48b6-a046-55ead8a12530" />
This PR introduces the concept of a state migration. When introducing new features, it's possible that there is existing transaction data that was not codified into a model that now needs to be. Rather than truncating the database, re-indexing blocks resulting in modifying existing StateRoots, this migration construct allows us to populate new models with existing data, leaving existing StateRoots unchanged, and codifying the changes in a sub-tree whos root is represented in the top-level StateRoot tree.  The StateMigrator specifies which migrations run at which block height for a given chain. Multiple migrations can be run for a single block and will be run in the order specified. Each migration will produce a root representing the changes made. Each of those roots are composed of the same StateRoot structure used at the very top-level, one for each block that was touched in the migration process. In the majority of cases where we're populating models with only a few events, these StateRoot trees will be rather sparse and only include the new model. Each migration works by: * Creating a new instance of the StateManager * Querying the database for the TransactionLogs that need to be processed * Groups them by block number * In the order of blockNumber ascending, feeds each log through the StateManager as it would have if it came through in real time. The same lifecycle of HandleLogStateChange --> CommitFinalState --> GenerateStateRoot is followed.
rewards v2.1 implementation
// memoize stakers into a map to remove duplicates and get the latest action | ||
for _, staker := range orderedStakers { | ||
key := fmt.Sprintf("%s-%s", staker.Staker, staker.Operator) | ||
collapsedStakers[key] = staker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't this lose all of the ordering stuff we just did?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ordering on the returned result doesnt really matter. We want to make sure we're getting the last delegation status for a staker/operator pair before the slashing event occurred to know if they were delegated or not. This is basically the same as doing:
select
staker,
operator,
strategy,
row_number() over (partition by staker, operator order by transaction_index desc, log_index desc, block_number desc) as rn
where
rn = 1
from staker_share_deltas as ssd | ||
on ssd.staker in @stakerAddresses | ||
and ssd.strategy = @strategy | ||
and ssd.block_number <= @blockNumber |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does <= here vs < everywhere else matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to update this one to be <
rather than <=
(all of them should be <
)
a4d6bb6
to
4f8209c
Compare
@@ -538,142 +534,6 @@ func Test_StakerSharesState(t *testing.T) { | |||
assert.Equal(t, strings.ToLower("0x3c42cd72639e3e8d11ab8d0072cc13bd5d8aa83c"), shareDiff.Staker) | |||
assert.Equal(t, "0xe523267698c81a372191136e477fdebfa33d9fb5", shareDiff.Strategy) | |||
}) | |||
|
|||
t.Run("Should capture delegate, deposit, slash in same block", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why delete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved it to a different location since it has a dependency on the new PrecommitProcessor
3cca7c8
to
2921dc8
Compare
Description
In order to properly handle slashing conditions, we need to know if any stakers delegated to a slashed operator in the current block being processed. By design, EigenState models are not aware of each other, so the current logic only handles stakers that were delegated in previous blocks.
This change introduces the concept of
PrecommitProcessors
that can handle massaging data across multiple models. In this case, theSlashingProcessor
inspects the accumulated state of the staker delegation model to find any newly delegated stakers and injects them into the StakerShares model through thePrecommitDelegatedStakers
struct field.Type of change
How Has This Been Tested?
Automated unit and integration tests
Checklist: