From 7dd015bfff20599146cc3312691f7cab522af058 Mon Sep 17 00:00:00 2001 From: Sean McGary Date: Fri, 6 Sep 2024 09:52:20 -0500 Subject: [PATCH 1/2] Remove delta table for operatorShares --- go.mod | 2 +- go.sum | 2 + .../eigenState/avsOperators/avsOperators.go | 2 +- internal/eigenState/eigenstate_test.go | 3 + .../operatorShares/operatorShares.go | 328 +++++++++++------- .../operatorShares/operatorShares_test.go | 6 + .../stakerDelegations/stakerDelegations.go | 2 +- .../stakerDelegations_test.go | 6 +- .../eigenState/stateManager/stateManager.go | 12 + internal/eigenState/types/types.go | 4 +- 10 files changed, 238 insertions(+), 129 deletions(-) diff --git a/go.mod b/go.mod index 9cf10add..91e6e2b2 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/google/flatbuffers v24.3.25+incompatible // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/holiman/uint256 v1.2.4 // indirect + github.com/holiman/uint256 v1.3.1 // indirect github.com/iden3/go-iden3-crypto v0.0.16 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect diff --git a/go.sum b/go.sum index a42ee72f..78e4284c 100644 --- a/go.sum +++ b/go.sum @@ -113,6 +113,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk= diff --git a/internal/eigenState/avsOperators/avsOperators.go b/internal/eigenState/avsOperators/avsOperators.go index 24bb9e12..6f2fc40c 100644 --- a/internal/eigenState/avsOperators/avsOperators.go +++ b/internal/eigenState/avsOperators/avsOperators.go @@ -155,7 +155,7 @@ func (a *AvsOperators) IsInterestingLog(log *storage.TransactionLog) bool { return a.BaseEigenState.IsInterestingLog(addresses, log) } -func (a *AvsOperators) StartBlockProcessing(blockNumber uint64) error { +func (a *AvsOperators) InitBlockProcessing(blockNumber uint64) error { return nil } diff --git a/internal/eigenState/eigenstate_test.go b/internal/eigenState/eigenstate_test.go index bc00174a..ec098f0a 100644 --- a/internal/eigenState/eigenstate_test.go +++ b/internal/eigenState/eigenstate_test.go @@ -59,6 +59,9 @@ func Test_EigenStateManager(t *testing.T) { assert.Equal(t, 0, indexes[0]) assert.Equal(t, 1, indexes[1]) + err = esm.InitProcessingForBlock(200) + assert.Nil(t, err) + root, err := esm.GenerateStateRoot(200) assert.Nil(t, err) assert.True(t, len(root) > 0) diff --git a/internal/eigenState/operatorShares/operatorShares.go b/internal/eigenState/operatorShares/operatorShares.go index fd85b3f7..b3eaff23 100644 --- a/internal/eigenState/operatorShares/operatorShares.go +++ b/internal/eigenState/operatorShares/operatorShares.go @@ -2,22 +2,21 @@ package operatorShares import ( "database/sql" - "encoding/json" "fmt" "github.com/Layr-Labs/sidecar/internal/config" "github.com/Layr-Labs/sidecar/internal/eigenState/base" "github.com/Layr-Labs/sidecar/internal/eigenState/stateManager" "github.com/Layr-Labs/sidecar/internal/eigenState/types" - "github.com/Layr-Labs/sidecar/internal/parser" "github.com/Layr-Labs/sidecar/internal/storage" "github.com/Layr-Labs/sidecar/internal/utils" + "github.com/holiman/uint256" "github.com/wealdtech/go-merkletree/v2" "github.com/wealdtech/go-merkletree/v2/keccak256" orderedmap "github.com/wk8/go-ordered-map/v2" "go.uber.org/zap" + "golang.org/x/xerrors" "gorm.io/gorm" "gorm.io/gorm/clause" - "math/big" "slices" "sort" "strings" @@ -46,6 +45,27 @@ type OperatorShares struct { CreatedAt time.Time } +type AccumulatedStateChange struct { + Operator string + Strategy string + Shares *uint256.Int + BlockNumber uint64 +} + +type OperatorSharesDiff struct { + Operator string + Strategy string + Shares *uint256.Int + BlockNumber uint64 + IsNew bool +} + +type SlotId string + +func NewSlotId(operator string, strategy string) SlotId { + return SlotId(fmt.Sprintf("%s_%s", operator, strategy)) +} + // Implements IEigenStateModel type OperatorSharesModel struct { base.BaseEigenState @@ -55,6 +75,9 @@ type OperatorSharesModel struct { Environment config.Environment logger *zap.Logger globalConfig *config.Config + + // Accumulates state changes for SlotIds, grouped by block number + stateAccumulator map[uint64]map[SlotId]*AccumulatedStateChange } func NewOperatorSharesModel( @@ -69,11 +92,12 @@ func NewOperatorSharesModel( BaseEigenState: base.BaseEigenState{ Logger: logger, }, - Db: grm, - Network: Network, - Environment: Environment, - logger: logger, - globalConfig: globalConfig, + Db: grm, + Network: Network, + Environment: Environment, + logger: logger, + globalConfig: globalConfig, + stateAccumulator: make(map[uint64]map[SlotId]*AccumulatedStateChange), } esm.RegisterState(model, 1) @@ -84,47 +108,60 @@ func (osm *OperatorSharesModel) GetModelName() string { return "OperatorSharesModel" } -func (osm *OperatorSharesModel) GetStateTransitions() (types.StateTransitions[OperatorShareChange], []uint64) { - stateChanges := make(types.StateTransitions[OperatorShareChange]) +func (osm *OperatorSharesModel) GetStateTransitions() (types.StateTransitions[AccumulatedStateChange], []uint64) { + stateChanges := make(types.StateTransitions[AccumulatedStateChange]) - stateChanges[0] = func(log *storage.TransactionLog) (*OperatorShareChange, error) { - arguments := make([]parser.Argument, 0) - err := json.Unmarshal([]byte(log.Arguments), &arguments) + stateChanges[0] = func(log *storage.TransactionLog) (*AccumulatedStateChange, error) { + arguments, err := osm.ParseLogArguments(log) if err != nil { - osm.logger.Sugar().Errorw("Failed to unmarshal arguments", - zap.Error(err), - zap.String("transactionHash", log.TransactionHash), - zap.Uint64("transactionIndex", log.TransactionIndex), - ) return nil, err } - outputData := make(map[string]interface{}) - err = json.Unmarshal([]byte(log.OutputData), &outputData) + outputData, err := osm.ParseLogOutput(log) if err != nil { - osm.logger.Sugar().Errorw("Failed to unmarshal outputData", + return nil, err + } + + // Sanity check to make sure we've got an initialized accumulator map for the block + if _, ok := osm.stateAccumulator[log.BlockNumber]; !ok { + return nil, xerrors.Errorf("No state accumulator found for block %d", log.BlockNumber) + } + + operator := arguments[0].Value.(string) + strategy := outputData["strategy"].(string) + sharesStr := outputData["shares"].(string) + + shares, err := uint256.FromDecimal(sharesStr) + if err != nil { + osm.logger.Sugar().Errorw("Failed to convert shares to uint256", zap.Error(err), + zap.String("shares", sharesStr), zap.String("transactionHash", log.TransactionHash), zap.Uint64("transactionIndex", log.TransactionIndex), + zap.Uint64("blockNumber", log.BlockNumber), ) - return nil, err + return nil, xerrors.Errorf("Failed to convert shares to uint256: %s", sharesStr) } - shares := big.Int{} - sharesInt, _ := shares.SetString(outputData["shares"].(string), 10) + // All shares are emitted as ABS(shares), so we need to negate the shares if the event is a decrease if log.EventName == "OperatorSharesDecreased" { - sharesInt.Mul(sharesInt, big.NewInt(-1)) + shares = shares.Neg(shares) } - change := &OperatorShareChange{ - Operator: arguments[0].Value.(string), - Strategy: outputData["strategy"].(string), - Shares: sharesInt.String(), - TransactionHash: log.TransactionHash, - TransactionIndex: log.TransactionIndex, - LogIndex: log.LogIndex, - BlockNumber: log.BlockNumber, + slotId := NewSlotId(operator, strategy) + record, ok := osm.stateAccumulator[log.BlockNumber][slotId] + if !ok { + record = &AccumulatedStateChange{ + Operator: operator, + Strategy: strategy, + Shares: shares, + BlockNumber: log.BlockNumber, + } + osm.stateAccumulator[log.BlockNumber][slotId] = record + } else { + record.Shares = record.Shares.Add(record.Shares, shares) } - return change, nil + + return record, nil } // Create an ordered list of block numbers @@ -155,7 +192,8 @@ func (osm *OperatorSharesModel) IsInterestingLog(log *storage.TransactionLog) bo return osm.BaseEigenState.IsInterestingLog(addresses, log) } -func (osm *OperatorSharesModel) StartBlockProcessing(blockNumber uint64) error { +func (osm *OperatorSharesModel) InitBlockProcessing(blockNumber uint64) error { + osm.stateAccumulator[blockNumber] = make(map[SlotId]*AccumulatedStateChange) return nil } @@ -170,127 +208,175 @@ func (osm *OperatorSharesModel) HandleStateChange(log *storage.TransactionLog) ( if err != nil { return nil, err } - - if change != nil { - wroteChange, err := osm.writeStateChange(change) - if err != nil { - return wroteChange, err - } - return wroteChange, nil + if change == nil { + return nil, xerrors.Errorf("No state change found for block %d", blockNumber) } + return change, nil } } return nil, nil } -func (osm *OperatorSharesModel) writeStateChange(change *OperatorShareChange) (interface{}, error) { - osm.logger.Sugar().Debugw("Writing state change", zap.Any("change", change)) - res := osm.Db.Model(&OperatorShareChange{}).Clauses(clause.Returning{}).Create(change) - if res.Error != nil { - osm.logger.Error("Failed to insert into avs_operator_changes", zap.Error(res.Error)) - return change, res.Error - } - return change, nil -} - -func (osm *OperatorSharesModel) CommitFinalState(blockNumber uint64) error { +func (osm *OperatorSharesModel) clonePreviousBlocksToNewBlock(blockNumber uint64) error { query := ` - with new_sum as ( - select - operator, - strategy, - sum(shares) as shares - from - operator_share_changes - where - block_number = @currentBlock - group by 1, 2 - ), - previous_values as ( + insert into operator_shares (operator, strategy, shares, block_number) select operator, strategy, - shares + shares, + @currentBlock as block_number from operator_shares where block_number = @previousBlock - ), - unioned_values as ( - (select operator, strategy, shares from previous_values) - union - (select operator, strategy, shares from new_sum) - ), - final_values as ( - select - operator, - strategy, - sum(shares) as shares - from unioned_values - group by 1, 2 - ) - insert into operator_shares (operator, strategy, shares, block_number) - select operator, strategy, shares, @currentBlock as block_number from final_values ` - res := osm.Db.Exec(query, sql.Named("currentBlock", blockNumber), sql.Named("previousBlock", blockNumber-1), ) + if res.Error != nil { - osm.logger.Sugar().Errorw("Failed to insert into operator_shares", zap.Error(res.Error)) + osm.logger.Sugar().Errorw("Failed to clone previous block state to new block", zap.Error(res.Error)) return res.Error } return nil } -func (osm *OperatorSharesModel) getDifferencesInStates(currentBlock uint64) ([]OperatorShares, error) { +// prepareState prepares the state for commit by adding the new state to the existing state +func (osm *OperatorSharesModel) prepareState(blockNumber uint64) ([]OperatorSharesDiff, error) { + preparedState := make([]OperatorSharesDiff, 0) + + accumulatedState, ok := osm.stateAccumulator[blockNumber] + if !ok { + err := xerrors.Errorf("No accumulated state found for block %d", blockNumber) + osm.logger.Sugar().Errorw(err.Error(), zap.Error(err), zap.Uint64("blockNumber", blockNumber)) + return nil, err + } + + slotIds := make([]SlotId, 0) + for slotId, _ := range accumulatedState { + slotIds = append(slotIds, slotId) + } + + // Find only the records from the previous block, that are modified in this block query := ` - with new_states as ( - select - concat(operator, '_', strategy) as slot_id, - operator, - strategy, - shares - from operator_shares - where block_number = @currentBlock - ), - previous_states as ( - select - concat(operator, '_', strategy) as slot_id, - operator, - strategy, - shares - from operator_shares - where block_number = @previousBlock - ), - diffs as ( - select slot_id, operator, strategy, shares from new_states - except - select slot_id, operator, strategy, shares from previous_states - ) - select operator, strategy, shares from diffs - order by strategy asc, operator asc + select + operator, + strategy, + shares + from operator_shares + where + block_number = @previousBlock + and concat(operator, '_', strategy) in @slotIds ` - - diffs := make([]OperatorShares, 0) - res := osm.Db. + existingRecords := make([]OperatorShares, 0) + res := osm.Db.Model(&OperatorShares{}). Raw(query, - sql.Named("currentBlock", currentBlock), - sql.Named("previousBlock", currentBlock-1), + sql.Named("previousBlock", blockNumber-1), + sql.Named("slotIds", slotIds), ). - Scan(&diffs) + Scan(&existingRecords) + if res.Error != nil { osm.logger.Sugar().Errorw("Failed to fetch operator_shares", zap.Error(res.Error)) return nil, res.Error } - return diffs, nil + + // Map the existing records to a map for easier lookup + mappedRecords := make(map[SlotId]OperatorShares) + for _, record := range existingRecords { + slotId := NewSlotId(record.Operator, record.Strategy) + mappedRecords[slotId] = record + } + + // Loop over our new state changes. + // If the record exists in the previous block, add the shares to the existing shares + for slotId, newState := range accumulatedState { + prepared := OperatorSharesDiff{ + Operator: newState.Operator, + Strategy: newState.Strategy, + Shares: newState.Shares, + BlockNumber: blockNumber, + IsNew: false, + } + + if existingRecord, ok := mappedRecords[slotId]; ok { + existingShares, err := uint256.FromDecimal(existingRecord.Shares) + if err != nil { + osm.logger.Sugar().Errorw("Failed to convert existing shares to uint256", zap.Error(err)) + continue + } + prepared.Shares = existingShares.Add(existingShares, newState.Shares) + } else { + // SlotID was not found in the previous block, so this is a new record + prepared.IsNew = true + } + + preparedState = append(preparedState, prepared) + } + return preparedState, nil +} + +func (osm *OperatorSharesModel) CommitFinalState(blockNumber uint64) error { + // Clone the previous block state to give us a reference point. + err := osm.clonePreviousBlocksToNewBlock(blockNumber) + if err != nil { + return err + } + + records, err := osm.prepareState(blockNumber) + if err != nil { + return err + } + + newRecords := make([]OperatorShares, 0) + updateRecords := make([]OperatorShares, 0) + + for _, record := range records { + r := &OperatorShares{ + Operator: record.Operator, + Strategy: record.Strategy, + Shares: record.Shares.String(), + BlockNumber: record.BlockNumber, + } + if record.IsNew { + newRecords = append(newRecords, *r) + } else { + updateRecords = append(updateRecords, *r) + } + } + + // Batch insert new records + if len(newRecords) > 0 { + res := osm.Db.Model(&OperatorShares{}).Clauses(clause.Returning{}).Create(&newRecords) + if res.Error != nil { + osm.logger.Sugar().Errorw("Failed to create new operator_shares records", zap.Error(res.Error)) + return res.Error + } + } + // Update existing records that were cloned from the previous block + if len(updateRecords) > 0 { + for _, record := range updateRecords { + res := osm.Db.Model(&OperatorShares{}). + Where("operator = ? and strategy = ? and block_number = ?", record.Operator, record.Strategy, record.BlockNumber). + Updates(map[string]interface{}{ + "shares": record.Shares, + }) + if res.Error != nil { + osm.logger.Sugar().Errorw("Failed to update operator_shares record", zap.Error(res.Error)) + return res.Error + } + } + } + + return nil } func (osm *OperatorSharesModel) ClearAccumulatedState(blockNumber uint64) error { - panic("implement me") + delete(osm.stateAccumulator, blockNumber) + return nil } func (osm *OperatorSharesModel) GenerateStateRoot(blockNumber uint64) (types.StateRoot, error) { - diffs, err := osm.getDifferencesInStates(blockNumber) + diffs, err := osm.prepareState(blockNumber) if err != nil { return "", err } @@ -302,7 +388,7 @@ func (osm *OperatorSharesModel) GenerateStateRoot(blockNumber uint64) (types.Sta return types.StateRoot(utils.ConvertBytesToString(fullTree.Root())), nil } -func (osm *OperatorSharesModel) merkelizeState(blockNumber uint64, diffs []OperatorShares) (*merkletree.MerkleTree, error) { +func (osm *OperatorSharesModel) merkelizeState(blockNumber uint64, diffs []OperatorSharesDiff) (*merkletree.MerkleTree, error) { // Create a merkle tree with the structure: // strategy: map[operators]: shares om := orderedmap.New[string, *orderedmap.OrderedMap[string, string]]() @@ -319,7 +405,7 @@ func (osm *OperatorSharesModel) merkelizeState(blockNumber uint64, diffs []Opera return nil, fmt.Errorf("strategy not in order") } } - existingStrategy.Set(diff.Operator, diff.Shares) + existingStrategy.Set(diff.Operator, diff.Shares.String()) prev := existingStrategy.GetPair(diff.Operator).Prev() if prev != nil && strings.Compare(prev.Key, diff.Operator) >= 0 { diff --git a/internal/eigenState/operatorShares/operatorShares_test.go b/internal/eigenState/operatorShares/operatorShares_test.go index 37eca7ca..e13fd4da 100644 --- a/internal/eigenState/operatorShares/operatorShares_test.go +++ b/internal/eigenState/operatorShares/operatorShares_test.go @@ -68,6 +68,9 @@ func Test_OperatorSharesState(t *testing.T) { model, err := NewOperatorSharesModel(esm, grm, cfg.Network, cfg.Environment, l, cfg) + err = model.InitBlockProcessing(blockNumber) + assert.Nil(t, err) + change, err := model.HandleStateChange(&log) assert.Nil(t, err) assert.NotNil(t, change) @@ -95,6 +98,9 @@ func Test_OperatorSharesState(t *testing.T) { model, err := NewOperatorSharesModel(esm, grm, cfg.Network, cfg.Environment, l, cfg) assert.Nil(t, err) + err = model.InitBlockProcessing(blockNumber) + assert.Nil(t, err) + stateChange, err := model.HandleStateChange(&log) assert.Nil(t, err) assert.NotNil(t, stateChange) diff --git a/internal/eigenState/stakerDelegations/stakerDelegations.go b/internal/eigenState/stakerDelegations/stakerDelegations.go index e03ec047..21e84b47 100644 --- a/internal/eigenState/stakerDelegations/stakerDelegations.go +++ b/internal/eigenState/stakerDelegations/stakerDelegations.go @@ -174,7 +174,7 @@ func (s *StakerDelegationsModel) IsInterestingLog(log *storage.TransactionLog) b } // StartBlockProcessing Initialize state accumulator for the block -func (s *StakerDelegationsModel) StartBlockProcessing(blockNumber uint64) error { +func (s *StakerDelegationsModel) InitBlockProcessing(blockNumber uint64) error { s.stateAccumulator[blockNumber] = make(map[SlotId]*AccumulatedStateChange) return nil } diff --git a/internal/eigenState/stakerDelegations/stakerDelegations_test.go b/internal/eigenState/stakerDelegations/stakerDelegations_test.go index a7ae67de..f2d82b98 100644 --- a/internal/eigenState/stakerDelegations/stakerDelegations_test.go +++ b/internal/eigenState/stakerDelegations/stakerDelegations_test.go @@ -68,7 +68,7 @@ func Test_DelegatedStakersState(t *testing.T) { assert.Equal(t, true, model.IsInterestingLog(&log)) - err = model.StartBlockProcessing(blockNumber) + err = model.InitBlockProcessing(blockNumber) assert.Nil(t, err) res, err := model.HandleStateChange(&log) @@ -105,7 +105,7 @@ func Test_DelegatedStakersState(t *testing.T) { assert.Equal(t, true, model.IsInterestingLog(&log)) - err = model.StartBlockProcessing(blockNumber) + err = model.InitBlockProcessing(blockNumber) assert.Nil(t, err) stateChange, err := model.HandleStateChange(&log) @@ -180,7 +180,7 @@ func Test_DelegatedStakersState(t *testing.T) { for _, log := range logs { assert.True(t, model.IsInterestingLog(log)) - err = model.StartBlockProcessing(log.BlockNumber) + err = model.InitBlockProcessing(log.BlockNumber) assert.Nil(t, err) stateChange, err := model.HandleStateChange(log) diff --git a/internal/eigenState/stateManager/stateManager.go b/internal/eigenState/stateManager/stateManager.go index b7d1583a..aea2fda7 100644 --- a/internal/eigenState/stateManager/stateManager.go +++ b/internal/eigenState/stateManager/stateManager.go @@ -45,6 +45,18 @@ func (e *EigenStateManager) HandleLogStateChange(log *storage.TransactionLog) er return nil } +func (e *EigenStateManager) InitProcessingForBlock(blockNumber uint64) error { + for _, index := range e.GetSortedModelIndexes() { + state := e.StateModels[index] + err := state.InitBlockProcessing(blockNumber) + if err != nil { + return err + } + } + return nil + +} + // With all transactions/logs processed for a block, commit the final state to the table func (e *EigenStateManager) CommitFinalState(blockNumber uint64) error { for _, index := range e.GetSortedModelIndexes() { diff --git a/internal/eigenState/types/types.go b/internal/eigenState/types/types.go index 6a6901a2..b369f761 100644 --- a/internal/eigenState/types/types.go +++ b/internal/eigenState/types/types.go @@ -15,9 +15,9 @@ type IEigenStateModel interface { //Determine if the log is interesting to the state model IsInterestingLog(log *storage.TransactionLog) bool - // StartBlockProcessing + // InitBlockProcessing // Perform any necessary setup for processing a block - StartBlockProcessing(blockNumber uint64) error + InitBlockProcessing(blockNumber uint64) error // HandleStateChange // Allow the state model to handle the state change From 8005a4e447d519272897a02f46e2319b505647fa Mon Sep 17 00:00:00 2001 From: Sean McGary Date: Fri, 6 Sep 2024 09:55:43 -0500 Subject: [PATCH 2/2] Cleanup and documentation --- .../operatorShares/operatorShares.go | 19 ++++--------------- .../stakerDelegations/stakerDelegations.go | 16 ++++------------ 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/internal/eigenState/operatorShares/operatorShares.go b/internal/eigenState/operatorShares/operatorShares.go index b3eaff23..13a07299 100644 --- a/internal/eigenState/operatorShares/operatorShares.go +++ b/internal/eigenState/operatorShares/operatorShares.go @@ -23,20 +23,7 @@ import ( "time" ) -// Changes table -type OperatorShareChange struct { - Id uint64 `gorm:"type:serial"` - Operator string - Strategy string - Shares string `gorm:"type:numeric"` - TransactionHash string - TransactionIndex uint64 - LogIndex uint64 - BlockNumber uint64 - CreatedAt time.Time -} - -// Block table +// OperatorShares represents the state of an operator's shares in a strategy at a given block number type OperatorShares struct { Operator string Strategy string @@ -45,6 +32,7 @@ type OperatorShares struct { CreatedAt time.Time } +// AccumulatedStateChange represents the accumulated state change for an operator's shares in a strategy at a given block number type AccumulatedStateChange struct { Operator string Strategy string @@ -60,6 +48,7 @@ type OperatorSharesDiff struct { IsNew bool } +// SlotId is a unique identifier for an operator's shares in a strategy type SlotId string func NewSlotId(operator string, strategy string) SlotId { @@ -69,7 +58,7 @@ func NewSlotId(operator string, strategy string) SlotId { // Implements IEigenStateModel type OperatorSharesModel struct { base.BaseEigenState - StateTransitions types.StateTransitions[OperatorShareChange] + StateTransitions types.StateTransitions[AccumulatedStateChange] Db *gorm.DB Network config.Network Environment config.Environment diff --git a/internal/eigenState/stakerDelegations/stakerDelegations.go b/internal/eigenState/stakerDelegations/stakerDelegations.go index 21e84b47..1ff0c49d 100644 --- a/internal/eigenState/stakerDelegations/stakerDelegations.go +++ b/internal/eigenState/stakerDelegations/stakerDelegations.go @@ -22,6 +22,7 @@ import ( "time" ) +// DelegatedStakers State model for staker delegations at block_number type DelegatedStakers struct { Staker string Operator string @@ -29,17 +30,7 @@ type DelegatedStakers struct { CreatedAt time.Time } -type StakerDelegationChange struct { - Staker string - Operator string - Delegated bool - TransactionHash string - TransactionIndex uint64 - LogIndex uint64 - BlockNumber uint64 - CreatedAt time.Time -} - +// AccumulatedStateChange represents the accumulated state change for a staker/operator pair type AccumulatedStateChange struct { Staker string Operator string @@ -47,6 +38,7 @@ type AccumulatedStateChange struct { Delegated bool } +// SlotId represents a unique identifier for a staker/operator pair type SlotId string func NewSlotId(staker string, operator string) SlotId { @@ -55,7 +47,7 @@ func NewSlotId(staker string, operator string) SlotId { type StakerDelegationsModel struct { base.BaseEigenState - StateTransitions types.StateTransitions[StakerDelegationChange] + StateTransitions types.StateTransitions[AccumulatedStateChange] Db *gorm.DB Network config.Network Environment config.Environment