Skip to content

Commit

Permalink
api: add validator history info
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew7234 committed Jul 30, 2024
1 parent db20667 commit 0f89b2d
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 9 deletions.
110 changes: 101 additions & 9 deletions api/spec/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ x-examples:
parameters-change:
- &parameters_change_1 '{"min_validators":null,"max_validators":"120","voting_power_distribution":null}'
epoch:
- &epoch_1 8048956
- &epoch_2 8048966
- &epoch_1 13402
- &epoch_2 13403
event-type:
- &event_type_1 'staking.escrow.take'
roothash-message-type:
Expand Down Expand Up @@ -508,7 +508,7 @@ paths:
required: true
schema:
allOf: [$ref: '#/components/schemas/StakingAddress']
description: The entity ID of the entity to return.
description: The address of the entity to return.
responses:
'200':
description: |
Expand All @@ -520,6 +520,43 @@ paths:
$ref: '#/components/schemas/Validator'
<<: *common_error_responses

/consensus/validators/{address}/history:
get:
summary: Returns historical information for a single validator.
parameters:
- *limit
- *offset
- in: query
name: from
schema:
type: integer
format: int64
description: A filter on minimum epoch number, inclusive.
example: *epoch_1
- in: query
name: to
schema:
type: integer
format: int64
description: A filter on maximum epoch number, inclusive.
example: *epoch_2
- in: path
name: address
required: true
schema:
allOf: [$ref: '#/components/schemas/StakingAddress']
description: The address of the entity to return.
responses:
'200':
description: |
A JSON object containing historical information for a
validator, grouped by epoch in reverse chronological order.
content:
application/json:
schema:
$ref: '#/components/schemas/EscrowHistory'
<<: *common_error_responses

/consensus/accounts:
get:
summary: |
Expand Down Expand Up @@ -1866,29 +1903,29 @@ components:
properties:
entity_address:
type: string
description: The staking address identifying this Validator.
description: The staking address identifying this validator.
example: *staking_address_1
entity_id:
x-go-name: EntityID
type: string
description: The public key identifying this Validator.
description: The public key identifying this validator.
example: *entity_id_1
node_id:
x-go-name: NodeID
type: string
description: The public key identifying this Validator's node.
description: The public key identifying this validator's node.
example: *node_id_1
escrow:
allOf: [$ref: '#/components/schemas/Escrow']
description: The escrow account data for this validator.
voting_power:
type: integer
format: int64
description: The voting power of this Validator.
description: The voting power of this validator.
voting_power_total:
type: integer
format: int64
description: The total voting power across all Validators.
description: The total voting power across all validators.
active:
type: boolean
description: Whether the entity has a node that is registered for being a validator, node is up to date, and has successfully registered itself. It may or may not be part of validator set.
Expand All @@ -1900,7 +1937,7 @@ components:
rank:
type: integer
format: uint64
description: The rank of the Validator, determined by voting power.
description: The rank of the validator, determined by voting power.
in_validator_set:
type: boolean
description: Whether the entity is part of the validator set (top <scheduler.params.max_validators> by stake among active entities).
Expand Down Expand Up @@ -1937,6 +1974,61 @@ components:
self_delegation_shares:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: The shares of tokens this validator has delegated to itself, and are NOT in the process of debonding.
active_balance_24:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: The active_balance of this validator account 24 hours ago.
num_delegators:
type: integer
format: uint64
description: The number of accounts that have delegated token to this account.

EscrowHistory:
allOf:
- $ref: '#/components/schemas/List'
- type: object
required: [history]
properties:
address:
type: string
description: The staking address of the validator.
example: *staking_address_1
history:
type: array
items:
allOf: [$ref: '#/components/schemas/HistoricalEscrowBalance']
description: Historical escrow balance data for a single address.

HistoricalEscrowBalance:
type: object
required: [epoch]
properties:
epoch:
type: integer
format: int64
description: The epoch number.
example: *epoch_1
active_balance:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: |
The amount of tokens that were delegated to this validator account,
at the start of this epoch, and are NOT in the process of debonding.
active_shares:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: |
The shares of tokens that were delegated to this validator account,
at the start of this epoch, and are NOT in the process of debonding.
debonding_balance:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: |
The amount of tokens that were delegated to this validator account
at the start of this epoch, but are also in the process of debonding
(i.e. they will be unstaked within ~2 weeks).
debonding_shares:
allOf: [$ref: '#/components/schemas/TextBigInt']
description: |
The shares of tokens that were delegated to this validator account
at the start of this epoch, but are also in the process of debonding
(i.e. they will be unstaked within ~2 weeks).
num_delegators:
type: integer
format: uint64
Expand Down
8 changes: 8 additions & 0 deletions api/v1/strict_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ func (srv *StrictServerImpl) GetConsensusValidatorsAddress(ctx context.Context,
return apiTypes.GetConsensusValidatorsAddress200JSONResponse(validators.Validators[0]), nil
}

func (srv *StrictServerImpl) GetConsensusValidatorsAddressHistory(ctx context.Context, request apiTypes.GetConsensusValidatorsAddressHistoryRequestObject) (apiTypes.GetConsensusValidatorsAddressHistoryResponseObject, error) {
history, err := srv.dbClient.ValidatorHistory(ctx, request.Address, request.Params)
if err != nil {
return nil, err
}
return apiTypes.GetConsensusValidatorsAddressHistory200JSONResponse(*history), nil
}

func (srv *StrictServerImpl) GetRuntimeBlocks(ctx context.Context, request apiTypes.GetRuntimeBlocksRequestObject) (apiTypes.GetRuntimeBlocksResponseObject, error) {
blocks, err := srv.dbClient.RuntimeBlocks(ctx, request.Params)
if err != nil {
Expand Down
39 changes: 39 additions & 0 deletions storage/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,7 @@ func (c *StorageClient) Validators(ctx context.Context, p apiTypes.GetConsensusV
&v.Escrow.DebondingShares,
&v.Escrow.SelfDelegationBalance,
&v.Escrow.SelfDelegationShares,
&v.Escrow.ActiveBalance24,
&v.Escrow.NumDelegators,
&v.VotingPower,
&v.VotingPowerTotal,
Expand Down Expand Up @@ -1312,6 +1313,44 @@ func (c *StorageClient) Validators(ctx context.Context, p apiTypes.GetConsensusV
return &vs, nil
}

func (c *StorageClient) ValidatorHistory(ctx context.Context, address staking.Address, p apiTypes.GetConsensusValidatorsAddressHistoryParams) (*EscrowHistory, error) {
res, err := c.withTotalCount(
ctx,
queries.ValidatorHistory,
address.String(),
p.From,
p.To,
p.Limit,
p.Offset,
)
if err != nil {
return nil, wrapError(err)
}
defer res.rows.Close()

h := EscrowHistory{
History: []HistoricalEscrowBalance{},
TotalCount: res.totalCount,
IsTotalCountClipped: res.isTotalCountClipped,
}
for res.rows.Next() {
b := HistoricalEscrowBalance{}
if err = res.rows.Scan(
&b.Epoch,
&b.ActiveBalance,
&b.ActiveShares,
&b.DebondingBalance,
&b.DebondingShares,
&b.NumDelegators,
); err != nil {
return nil, wrapError(err)
}
h.History = append(h.History, b)
}

return &h, nil
}

// RuntimeBlocks returns a list of runtime blocks.
func (c *StorageClient) RuntimeBlocks(ctx context.Context, p apiTypes.GetRuntimeBlocksParams) (*RuntimeBlockList, error) {
hash, err := canonicalizedHash(p.Hash)
Expand Down
23 changes: 23 additions & 0 deletions storage/client/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ const (
COALESCE (
self_delegations.shares
, 0) AS self_delegation_shares,
history.validators.escrow_balance_active AS active_balance_24,
COALESCE (
delegators_count.count
, 0) AS num_delegators,
Expand All @@ -357,6 +358,11 @@ const (
JOIN chain.blocks ON chain.entities.start_block = chain.blocks.height
LEFT JOIN chain.commissions ON chain.entities.address = chain.commissions.address
LEFT JOIN self_delegations ON chain.entities.address = self_delegations.address
LEFT JOIN history.validators ON chain.entities.id = history.validators.id
-- Find the epoch id from 24 hours ago. Each epoch is ~1hr.
AND history.validators.epoch = (SELECT id - 24 from chain.epochs
ORDER BY id DESC
LIMIT 1)
LEFT JOIN delegators_count ON chain.entities.address = delegators_count.address
LEFT JOIN validator_nodes ON validator_nodes.address = entities.address
JOIN validator_rank ON chain.entities.address = validator_rank.address
Expand All @@ -369,6 +375,23 @@ const (
LIMIT $3::bigint
OFFSET $4::bigint`

ValidatorHistory = `
SELECT
epoch,
escrow_balance_active,
escrow_total_shares_active,
escrow_balance_debonding,
escrow_total_shares_debonding,
num_delegators
FROM chain.entities
JOIN history.validators ON chain.entities.id = history.validators.id
WHERE (chain.entities.address = $1::text) AND
($2::bigint IS NULL OR history.validators.epoch >= $2::bigint) AND
($3::bigint IS NULL OR history.validators.epoch <= $3::bigint)
ORDER BY epoch DESC
LIMIT $4::bigint
OFFSET $5::bigint`

RuntimeBlocks = `
SELECT round, block_hash, timestamp, num_transactions, size, gas_used
FROM chain.runtime_blocks
Expand Down
6 changes: 6 additions & 0 deletions storage/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ type ValidatorMedia = api.ValidatorMedia
// ValidatorCommissionBound is the commission bound for a validator.
type ValidatorCommissionBound = api.ValidatorCommissionBound

// EscrowHistory is the storage response for GetValidatorHistory.
type EscrowHistory = api.EscrowHistory

// HistoricalEscrowBalance is the escrow information for a validator at a given epoch.
type HistoricalEscrowBalance = api.HistoricalEscrowBalance

// RuntimeBlockList is the storage response for RuntimeListBlocks.
type RuntimeBlockList = api.RuntimeBlockList

Expand Down
22 changes: 22 additions & 0 deletions tests/e2e_regression/damask/expected/validator_history.body
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"history": [
{
"active_balance": "75369956295476647",
"active_shares": "62390383512876854",
"debonding_balance": "683221451594757",
"debonding_shares": "683221451594757",
"epoch": 13403,
"num_delegators": 10840
},
{
"active_balance": "75368981020862238",
"active_shares": "62390367366454536",
"debonding_balance": "683221451594757",
"debonding_shares": "683221451594757",
"epoch": 13402,
"num_delegators": 10840
}
],
"is_total_count_clipped": false,
"total_count": 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: UNINTERESTING
Content-Length: UNINTERESTING

1 change: 1 addition & 0 deletions tests/e2e_regression/damask/test_cases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ testCases=(
'epoch /v1/consensus/epochs/13403'
'tx /v1/consensus/transactions/f7a03e0912d355901ee794e5fec79a6b4c91363fc27d953596ee6de5c1492798'
'validator /v1/consensus/validators/oasis1qr3w66akc8ud9a4zsgyjw2muvcfjgfszn5ycgc0a'
'validator_history /v1/consensus/validators/oasis1qq0xmq7r0z9sdv02t5j9zs7en3n6574gtg8v9fyt/history'
'emerald_tx /v1/emerald/transactions/a6471a9c6f3307087586da9156f3c9876fbbaf4b23910cd9a2ac524a54d0aefe'
'emerald_failed_tx /v1/emerald/transactions/a7e76442c52a3cb81f719bde26c9a6179bd3415f96740d91a93ee8f205b45150'
'emerald_token_nfts /v1/emerald/evm_tokens/oasis1qqewaa87rnyshyqs7yutnnpzzetejecgeu005l8u/nfts'
Expand Down
1 change: 1 addition & 0 deletions tests/e2e_regression/eden/test_cases.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ testCases=(
'epoch /v1/consensus/epochs/28017'
'tx /v1/consensus/transactions/142d43e5194b738ab2223f8d0b42326fab06edd714a8cefc59a078b89b5de057'
'validator /v1/consensus/validators/oasis1qqekv2ymgzmd8j2s2u7g0hhc7e77e654kvwqtjwm'
'validator_history /v1/consensus/validators/oasis1qqekv2ymgzmd8j2s2u7g0hhc7e77e654kvwqtjwm/history'
'emerald_tx /v1/emerald/transactions/ec1173a69272c67f126f18012019d19cd25199e831f9417b6206fb7844406f9d'
'emerald_failed_tx /v1/emerald/transactions/35fdc8261dd81be8187c858aa9a623085494baf0565d414f48562a856147c093'
'emerald_events_by_nft /v1/emerald/events?contract_address=oasis1qz29t7nxkwfqgfk36uqqs9pzuzdt8zmrjud5mehx&nft_id=1'
Expand Down

0 comments on commit 0f89b2d

Please sign in to comment.