From 28329723662ace607db693af8a424cbc36dea1c1 Mon Sep 17 00:00:00 2001 From: Sean McGary Date: Thu, 16 Jan 2025 08:34:34 -0600 Subject: [PATCH] wip - ListStakerShares rpc --- go.mod | 2 +- go.sum | 2 + pkg/rpcServer/protocolHandlers.go | 20 ++++- pkg/rpcServer/server.go | 36 +++++---- pkg/service/protocolDataService/protocol.go | 86 ++++++++++++++++++--- 5 files changed, 115 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index ea1940a9..3cba7042 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/DataDog/datadog-go/v5 v5.5.0 github.com/Layr-Labs/eigenlayer-contracts v0.4.1-holesky-pepe.0.20240813143901-00fc4b95e9c1 github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.13 - github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115220323-135176acb92b + github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115230325-93c4ebccbeb7 github.com/ethereum/go-ethereum v1.14.9 github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 46bbb474..3c546f54 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/Layr-Labs/protocol-apis v1.1.1-0.20250114181701-acb87ef4eeb5 h1:0PLxb github.com/Layr-Labs/protocol-apis v1.1.1-0.20250114181701-acb87ef4eeb5/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115220323-135176acb92b h1:eJmPAq3s+AwOrQUjSFXILCzUstDZobwYEraOZ2NFC1M= github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115220323-135176acb92b/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= +github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115230325-93c4ebccbeb7 h1:zTOIFjJcCzOZ1PBk9jtoW/bsKSyRzvQyTG2Beutpiuk= +github.com/Layr-Labs/protocol-apis v1.1.1-0.20250115230325-93c4ebccbeb7/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= diff --git a/pkg/rpcServer/protocolHandlers.go b/pkg/rpcServer/protocolHandlers.go index 68aaf179..9a829545 100644 --- a/pkg/rpcServer/protocolHandlers.go +++ b/pkg/rpcServer/protocolHandlers.go @@ -26,6 +26,22 @@ func (rpc *RpcServer) GetDelegatedStakersForOperator(ctx context.Context, reques } func (rpc *RpcServer) GetStakerShares(ctx context.Context, request *protocolV1.GetStakerSharesRequest) (*protocolV1.GetStakerSharesResponse, error) { - //TODO implement me - panic("implement me") + shares, err := rpc.protocolDataService.ListStakerShares(request.GetStakerAddress(), request.GetBlockHeight()) + if err != nil { + return nil, err + } + + stakerShares := make([]*protocolV1.StakerShare, 0, len(shares)) + for _, share := range shares { + stakerShares = append(stakerShares, &protocolV1.StakerShare{ + Strategy: share.Strategy, + Shares: share.Shares, + OperatorAddress: share.Operator, + AvsAddresses: share.AvsAddresses, + }) + } + + return &protocolV1.GetStakerSharesResponse{ + Shares: stakerShares, + }, nil } diff --git a/pkg/rpcServer/server.go b/pkg/rpcServer/server.go index 6212d04e..97a70967 100644 --- a/pkg/rpcServer/server.go +++ b/pkg/rpcServer/server.go @@ -15,6 +15,7 @@ import ( "github.com/Layr-Labs/sidecar/pkg/proofs" "github.com/Layr-Labs/sidecar/pkg/rewards" "github.com/Layr-Labs/sidecar/pkg/rewardsCalculatorQueue" + "github.com/Layr-Labs/sidecar/pkg/service/protocolDataService" "github.com/Layr-Labs/sidecar/pkg/storage" grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap" grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags" @@ -34,14 +35,15 @@ type RpcServerConfig struct { } type RpcServer struct { - Logger *zap.Logger - rpcConfig *RpcServerConfig - blockStore storage.BlockStore - stateManager *stateManager.EigenStateManager - rewardsCalculator *rewards.RewardsCalculator - rewardsQueue *rewardsCalculatorQueue.RewardsCalculatorQueue - eventBus eventBusTypes.IEventBus - rewardsProofs *proofs.RewardsProofsStore + Logger *zap.Logger + rpcConfig *RpcServerConfig + blockStore storage.BlockStore + stateManager *stateManager.EigenStateManager + rewardsCalculator *rewards.RewardsCalculator + rewardsQueue *rewardsCalculatorQueue.RewardsCalculatorQueue + eventBus eventBusTypes.IEventBus + rewardsProofs *proofs.RewardsProofsStore + protocolDataService *protocolDataService.ProtocolDataService } func NewRpcServer( @@ -52,17 +54,19 @@ func NewRpcServer( rcq *rewardsCalculatorQueue.RewardsCalculatorQueue, eb eventBusTypes.IEventBus, rp *proofs.RewardsProofsStore, + pds *protocolDataService.ProtocolDataService, l *zap.Logger, ) *RpcServer { server := &RpcServer{ - rpcConfig: config, - blockStore: bs, - stateManager: sm, - rewardsCalculator: rc, - rewardsQueue: rcq, - eventBus: eb, - rewardsProofs: rp, - Logger: l, + rpcConfig: config, + blockStore: bs, + stateManager: sm, + rewardsCalculator: rc, + rewardsQueue: rcq, + eventBus: eb, + rewardsProofs: rp, + protocolDataService: pds, + Logger: l, } return server diff --git a/pkg/service/protocolDataService/protocol.go b/pkg/service/protocolDataService/protocol.go index 533752c9..0f86838b 100644 --- a/pkg/service/protocolDataService/protocol.go +++ b/pkg/service/protocolDataService/protocol.go @@ -1,9 +1,10 @@ package protocolDataService import ( + "database/sql" "github.com/Layr-Labs/sidecar/internal/config" - "github.com/Layr-Labs/sidecar/pkg/eigenState/stakerShares" "github.com/Layr-Labs/sidecar/pkg/service/types" + "github.com/Layr-Labs/sidecar/pkg/storage" "go.uber.org/zap" "gorm.io/gorm" ) @@ -42,20 +43,81 @@ func (pds *ProtocolDataService) ListDelegatedStakersForOperator(operator string, return nil, nil } -func (pds *ProtocolDataService) ListStakerShares(staker string, blockHeight uint64) ([]*stakerShares.StakerShareDeltas, error) { - shares := make([]*stakerShares.StakerShareDeltas, 0) +type StakerShares struct { + Staker string + Strategy string + Shares string + BlockHeight uint64 + Operator *string + Delegated *bool + AvsAddresses []string +} - whereParams := []interface{}{staker} - where := "staker = ?" - if blockHeight > 0 { - where += " AND block_height <= ?" - whereParams = append(whereParams, blockHeight) - } +// ListStakerShares returns the shares of a staker at a given block height, including the operator they were delegated to +// and the addresses of the AVSs the operator was registered to. +// +// If not blockHeight is provided, the most recently indexed block will be used. +func (pds *ProtocolDataService) ListStakerShares(staker string, blockHeight uint64) ([]*StakerShares, error) { + shares := make([]*StakerShares, 0) - res := pds.db.Model(&stakerShares.StakerShareDeltas{}). - Where(where, whereParams...). - Find(&shares) + if blockHeight == 0 { + var currentBlock *storage.Block + res := pds.db.Model(&storage.Block{}).Order("number desc").First(¤tBlock) + if res.Error != nil { + return nil, res.Error + } + blockHeight = currentBlock.Number + } + query := ` + with distinct_staker_strategies as ( + select + ssd.staker, + ssd.strategy, + ssd.shares, + ssd.block_number, + row_number() over (partition by ssd.staker, ssd.strategy order by ssd.block_number desc) as rn + from sidecar_mainnet_ethereum.staker_shares as ssd + where + ssd.staker = @staker + and block_number <= @blockHeight + order by block_number desc + ) + select + dss.*, + dsc.operator, + dsc.delegated, + aosc.avs_list as avs_addresses + from distinct_staker_strategies as dss + left join lateral ( + select + sdc.staker, + sdc.operator, + sdc.delegated, + row_number() over (partition by sdc.staker order by sdc.block_number desc, sdc.log_index) as rn + from sidecar_mainnet_ethereum.staker_delegation_changes as sdc + where + sdc.staker = dss.staker + and sdc.block_number <= dss.block_number + order by block_number desc + ) as dsc on (dsc.rn = 1) + left join lateral ( + select + jsonb_agg(distinct aosc.avs) as avs_list + from sidecar_mainnet_ethereum.avs_operator_state_changes aosc + where + aosc.operator = dsc.operator + and aosc.block_number <= dss.block_number + and aosc.registered = true + ) as aosc on true + where + dss.rn = 1 + order by block_number desc; + ` + res := pds.db.Raw(query, + sql.Named("staker", staker), + sql.Named("blockHeight", blockHeight), + ).Scan(&shares) if res.Error != nil { return nil, res.Error }