Skip to content

Commit

Permalink
Make operator stake API returns operator address
Browse files Browse the repository at this point in the history
  • Loading branch information
jianoaix committed Feb 18, 2025
1 parent 268a3a9 commit b9aa9e4
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 15 deletions.
11 changes: 5 additions & 6 deletions disperser/dataapi/docs/v2/V2_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,8 @@ const docTemplateV2 = `{
}
]
},
"reservation_period": {
"description": "ReservationPeriod represents the range of time at which the dispersal is made",
"timestamp": {
"description": "Timestamp represents the nanosecond of the dispersal request creation",
"type": "integer"
}
}
Expand Down Expand Up @@ -879,10 +879,6 @@ const docTemplateV2 = `{
"items": {
"type": "integer"
}
},
"salt": {
"description": "Salt is used to make blob intentionally unique when everything else is the same",
"type": "integer"
}
}
},
Expand Down Expand Up @@ -1326,6 +1322,9 @@ const docTemplateV2 = `{
"v2.OperatorStake": {
"type": "object",
"properties": {
"operator_address": {
"type": "string"
},
"operator_id": {
"type": "string"
},
Expand Down
7 changes: 5 additions & 2 deletions disperser/dataapi/docs/v2/V2_swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -690,8 +690,8 @@
}
]
},
"reservation_period": {
"description": "ReservationPeriod represents the range of time at which the dispersal is made",
"timestamp": {
"description": "Timestamp represents the nanosecond of the dispersal request creation",
"type": "integer"
}
}
Expand Down Expand Up @@ -1319,6 +1319,9 @@
"v2.OperatorStake": {
"type": "object",
"properties": {
"operator_address": {
"type": "string"
},
"operator_id": {
"type": "string"
},
Expand Down
8 changes: 5 additions & 3 deletions disperser/dataapi/docs/v2/V2_swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ definitions:
- $ref: '#/definitions/big.Int'
description: CumulativePayment represents the total amount of payment (in
wei) made by the user up to this point
reservation_period:
description: ReservationPeriod represents the range of time at which the dispersal
is made
timestamp:
description: Timestamp represents the nanosecond of the dispersal request
creation
type: integer
type: object
core.Signature:
Expand Down Expand Up @@ -457,6 +457,8 @@ definitions:
type: object
v2.OperatorStake:
properties:
operator_address:
type: string
operator_id:
type: string
quorum_id:
Expand Down
3 changes: 1 addition & 2 deletions disperser/dataapi/operator_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,7 @@ func (oh *OperatorHandler) GetOperatorsStakeAtBlock(ctx context.Context, operato
return nil, fmt.Errorf("failed to fetch indexed operator state: %w", err)
}

tqs, quorumsStake := operators.GetRankedOperators(state)
oh.metrics.UpdateOperatorsStake(tqs, quorumsStake)
_, quorumsStake := operators.GetRankedOperators(state)

stakeRanked := make(map[string][]*OperatorStake)
for q, operators := range quorumsStake {
Expand Down
1 change: 1 addition & 0 deletions disperser/dataapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ type (
OperatorStake struct {
QuorumId string `json:"quorum_id"`
OperatorId string `json:"operator_id"`
OperatorAddress string `json:"operator_address"`
StakePercentage float64 `json:"stake_percentage"`
Rank int `json:"rank"`
}
Expand Down
38 changes: 37 additions & 1 deletion disperser/dataapi/v2/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ func (s *ServerV2) FetchOperatorSigningInfo(c *gin.Context) {
// @Router /operators/stake [get]
func (s *ServerV2) FetchOperatorsStake(c *gin.Context) {
handlerStart := time.Now()
ctx := c.Request.Context()

operatorId := c.DefaultQuery("operator_id", "")
s.logger.Info("getting operators stake distribution", "operatorId", operatorId)
Expand All @@ -166,14 +167,49 @@ func (s *ServerV2) FetchOperatorsStake(c *gin.Context) {
errorResponse(c, fmt.Errorf("failed to get current block number: %w", err))
return
}
operatorsStakeResponse, err := s.operatorHandler.GetOperatorsStake(c.Request.Context(), operatorId)
operatorsStakeResponse, err := s.operatorHandler.GetOperatorsStakeAtBlock(ctx, operatorId, uint32(currentBlock))
if err != nil {
s.metrics.IncrementFailedRequestNum("FetchOperatorsStake")
errorResponse(c, fmt.Errorf("failed to get operator stake: %w", err))
return
}
operatorsStakeResponse.CurrentBlock = uint32(currentBlock)

// Get operators' addresses in batch
operatorsSeen := make(map[string]struct{}, 0)
for _, ops := range operatorsStakeResponse.StakeRankedOperators {
for _, op := range ops {
operatorsSeen[op.OperatorId] = struct{}{}
}
}
operatorIDs := make([]core.OperatorID, 0)
for id := range operatorsSeen {
opId, err := core.OperatorIDFromHex(id)
if err != nil {
s.metrics.IncrementFailedRequestNum("FetchOperatorsStake")
errorResponse(c, fmt.Errorf("malformed operator ID: %w", err))
return
}
operatorIDs = append(operatorIDs, opId)
}
// Get the address for the operators.
// operatorAddresses[i] is the address for operatorIDs[i].
operatorAddresses, err := s.chainReader.BatchOperatorIDToAddress(ctx, operatorIDs)
if err != nil {
s.metrics.IncrementFailedRequestNum("FetchOperatorsStake")
errorResponse(c, fmt.Errorf("failed to get operator addresses from IDs: %w", err))
return
}
idToAddress := make(map[string]string, 0)
for i := range operatorIDs {
idToAddress[operatorIDs[i].Hex()] = operatorAddresses[i].Hex()
}
for _, ops := range operatorsStakeResponse.StakeRankedOperators {
for _, op := range ops {
op.OperatorAddress = idToAddress[op.OperatorId]
}
}

s.metrics.IncrementSuccessfulRequestNum("FetchOperatorsStake")
s.metrics.ObserveLatency("FetchOperatorsStake", time.Since(handlerStart))
c.Writer.Header().Set(cacheControlParam, fmt.Sprintf("max-age=%d", maxOperatorsStakeAge))
Expand Down
1 change: 1 addition & 0 deletions disperser/dataapi/v2/server_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type (
OperatorStake struct {
QuorumId string `json:"quorum_id"`
OperatorId string `json:"operator_id"`
OperatorAddress string `json:"operator_address"`
StakePercentage float64 `json:"stake_percentage"`
Rank int `json:"rank"`
}
Expand Down
33 changes: 32 additions & 1 deletion disperser/dataapi/v2/server_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1648,26 +1648,57 @@ func TestFetchOperatorsStake(t *testing.T) {

mockIndexedChainState.On("GetCurrentBlockNumber").Return(uint(1), nil)

addr0 := gethcommon.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa")
addr1 := gethcommon.HexToAddress("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
mockTx.On("BatchOperatorIDToAddress").Return(
func(ids []core.OperatorID) []gethcommon.Address {
result := make([]gethcommon.Address, len(ids))
for i, id := range ids {
if id == opId0 {
result[i] = addr0
} else if id == opId1 {
result[i] = addr1
} else {
result[i] = gethcommon.Address{}
}
}
return result
},
nil,
)

r.GET("/v2/operators/stake", testDataApiServerV2.FetchOperatorsStake)

w := executeRequest(t, r, http.MethodGet, "/v2/operators/stake")
response := decodeResponseBody[dataapi.OperatorsStakeResponse](t, w)

// The quorums and the operators in the quorum are defined in "mockChainState"
// There are 3 quorums (0, 1) and a "total" entry for TotalQuorumStake
// There are 2 quorums (0, 1)
require.Equal(t, 2, len(response.StakeRankedOperators))
checkAddress := func(op *dataapi.OperatorStake) {
if op.OperatorId == opId0.Hex() {
assert.Equal(t, addr0.Hex(), op.OperatorAddress)
}
if op.OperatorId == opId1.Hex() {
assert.Equal(t, addr1.Hex(), op.OperatorAddress)
}
}
// Quorum 0
ops, ok := response.StakeRankedOperators["0"]
require.True(t, ok)
require.Equal(t, 2, len(ops))
assert.Equal(t, opId0.Hex(), ops[0].OperatorId)
assert.Equal(t, opId1.Hex(), ops[1].OperatorId)
checkAddress(ops[0])
checkAddress(ops[1])
// Quorum 1
ops, ok = response.StakeRankedOperators["1"]
require.True(t, ok)
require.Equal(t, 2, len(ops))
assert.Equal(t, opId1.Hex(), ops[0].OperatorId)
assert.Equal(t, opId0.Hex(), ops[1].OperatorId)
checkAddress(ops[0])
checkAddress(ops[1])
}

func TestFetchMetricsSummary(t *testing.T) {
Expand Down

0 comments on commit b9aa9e4

Please sign in to comment.