Skip to content

Commit

Permalink
api/consensus: validator proposed blocks endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus committed Oct 8, 2024
1 parent b4f370b commit d6b4b43
Show file tree
Hide file tree
Showing 12 changed files with 1,281 additions and 3 deletions.
1 change: 1 addition & 0 deletions .changelog/764.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
api/consensus: validator proposed blocks endpoint
35 changes: 35 additions & 0 deletions api/spec/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,29 @@ paths:
$ref: '#/components/schemas/ValidatorHistory'
<<: *common_error_responses

/consensus/validators/{address}/proposed_blocks:
get:
summary: Returns information about proposed blocks for a single validator.
parameters:
- *limit
- *offset
- in: path
name: address
required: true
schema:
allOf: [$ref: '#/components/schemas/StakingAddress']
description: The address of the entity to return data for.
responses:
'200':
description: |
A JSON object containing information about blocks the validator
has proposed.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidatorProposedBlocks'
<<: *common_error_responses

/consensus/accounts:
get:
summary: |
Expand Down Expand Up @@ -2132,6 +2155,18 @@ components:
description: |
A list of nodes registered at the consensus layer.
ValidatorProposedBlocks:
allOf:
- $ref: '#/components/schemas/List'
- type: object
required: [blocks]
properties:
blocks:
type: array
items:
allOf: [$ref: '#/components/schemas/Block']
description: A list of blocks proposed by the validator.

Node:
type: object
required: [id, entity_id, expiration, tls_pubkey, tls_next_pubkey, p2p_pubkey, consensus_pubkey, roles]
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 @@ -278,6 +278,14 @@ func (srv *StrictServerImpl) GetConsensusValidatorsAddressHistory(ctx context.Co
return apiTypes.GetConsensusValidatorsAddressHistory200JSONResponse(*history), nil
}

func (srv *StrictServerImpl) GetConsensusValidatorsAddressProposedBlocks(ctx context.Context, request apiTypes.GetConsensusValidatorsAddressProposedBlocksRequestObject) (apiTypes.GetConsensusValidatorsAddressProposedBlocksResponseObject, error) {
blocks, err := srv.dbClient.ValidatorProposedBlocks(ctx, request.Address, request.Params)
if err != nil {
return nil, err
}
return apiTypes.GetConsensusValidatorsAddressProposedBlocks200JSONResponse(*blocks), 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
59 changes: 59 additions & 0 deletions storage/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ func (c *StorageClient) Blocks(ctx context.Context, r apiTypes.GetConsensusBlock
r.After,
r.Before,
hash,
nil,
r.Limit,
r.Offset,
)
Expand Down Expand Up @@ -1344,6 +1345,64 @@ func (c *StorageClient) ValidatorHistory(ctx context.Context, address staking.Ad
return &h, nil
}

func (c *StorageClient) ValidatorProposedBlocks(ctx context.Context, address staking.Address, p apiTypes.GetConsensusValidatorsAddressProposedBlocksParams) (*ValidatorProposedBlocks, error) {
// Fetch entity ID of the validator so we can efficiently query for blocks.
var entityID string
if err := c.db.QueryRow(
ctx,
queries.ValidatorEntityID,
address.String(),
).Scan(&entityID); err != nil {
// Empty response for a non-existing address.
return &ValidatorProposedBlocks{}, nil
}

res, err := c.withTotalCount(
ctx,
queries.Blocks,
nil,
nil,
nil,
nil,
nil,
entityID,
p.Limit,
p.Offset,
)
if err != nil {
return nil, wrapError(err)
}
defer res.rows.Close()

h := ValidatorProposedBlocks{
Blocks: []Block{},
TotalCount: res.totalCount,
IsTotalCountClipped: res.isTotalCountClipped,
}
for res.rows.Next() {
var b Block
var proposerRow entityInfoRow
var signerRows []entityInfoRow
if err = res.rows.Scan(
&b.Height,
&b.Hash,
&b.Timestamp,
&b.NumTransactions,
&b.GasLimit,
&b.SizeLimit,
&b.Epoch,
&b.StateRoot,
&proposerRow,
&signerRows,
); err != nil {
return nil, wrapError(err)
}
h.Blocks = append(h.Blocks, 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
12 changes: 9 additions & 3 deletions storage/client/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ const (
($2::bigint IS NULL OR height <= $2::bigint) AND
($3::timestamptz IS NULL OR time >= $3::timestamptz) AND
($4::timestamptz IS NULL OR time < $4::timestamptz) AND
($5::text IS NULL OR block_hash = $5::text)
($5::text IS NULL OR block_hash = $5::text) AND
($6::text IS NULL OR proposer_entity_id = $6::text)
ORDER BY height DESC
LIMIT $6::bigint
OFFSET $7::bigint`
LIMIT $7::bigint
OFFSET $8::bigint`

Block = `
SELECT height, block_hash, time, num_txs, gas_limit, size_limit, epoch, state_root
Expand Down Expand Up @@ -427,6 +428,11 @@ const (
LIMIT $4::bigint
OFFSET $5::bigint`

ValidatorEntityID = `
SELECT id
FROM chain.entities
WHERE address = $1::text`

RuntimeBlocks = `
SELECT round, block_hash, timestamp, num_transactions, size, gas_used
FROM chain.runtime_blocks
Expand Down
3 changes: 3 additions & 0 deletions storage/client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ type ValidatorCommissionBound = api.ValidatorCommissionBound
// ValidatorHistory is the storage response for GetValidatorHistory.
type ValidatorHistory = api.ValidatorHistory

// ValidatorProposedBlocks is the storage response for the GetValidatorProposedBlocks.
type ValidatorProposedBlocks = api.ValidatorProposedBlocks

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

Expand Down
146 changes: 146 additions & 0 deletions tests/e2e_regression/damask/expected/validator_proposed_blocks.body
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
{
"blocks": [
{
"epoch": 13403,
"gas_limit": "0",
"hash": "28e5d289b22555ede510c6c6014e054c4b22fde1e07e455f9ecd23acd710f898",
"height": 8049914,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "d848582d4e038accea6c77ee0f0b203d150ef89f32ef840b99b397ed4c1f4e03",
"timestamp": "2022-04-11T12:41:03Z"
},
{
"epoch": 13403,
"gas_limit": "0",
"hash": "6165753095d547217b320475ad4314f6262d26db513bc5cfa978b7a4ded314e3",
"height": 8049844,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "743de138e7ab3e45bf94e12d493e7bd1a9b2b725e477b9b391de0ad03b85fe8d",
"timestamp": "2022-04-11T12:34:18Z"
},
{
"epoch": 13403,
"gas_limit": "0",
"hash": "64e9e55207d05e6db269333542c010746ee4ece84dedd310c8df1bb801fc0e59",
"height": 8049779,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "0b8152fa3c1fbc0047d2811dda5304cb5a192817d2bc7f5200133089b4afb930",
"timestamp": "2022-04-11T12:28:03Z"
},
{
"epoch": 13403,
"gas_limit": "0",
"hash": "5c9b4cfa4700b384414a4ca7ccba7a9b9add0f32a66f98a6e3820574ca8adf8e",
"height": 8049719,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "f42ae50ebfffb11a3e5fda0b509dc3b87d6e635728ad71278b27bbf76a76ac9f",
"timestamp": "2022-04-11T12:22:15Z"
},
{
"epoch": 13403,
"gas_limit": "0",
"hash": "6ed8d457189c9d7ca7e73908675816c83f22b2c98ff1ca3d3dc2b6ec46d7f56b",
"height": 8049654,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "be158217ba8dfb0aaede4a06226f1e139f50f439e96397e9a26dcfdc19a1ec52",
"timestamp": "2022-04-11T12:15:59Z"
},
{
"epoch": 13403,
"gas_limit": "0",
"hash": "976e0c27b77808e67f086113f0b3e1671d9d2063cd8b3e392bdc255aa67ea1e8",
"height": 8049589,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "847cb490040171a14342c0f5aa166aeba760fa08f02a8a8bf22e856392d70023",
"timestamp": "2022-04-11T12:09:41Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "f55247083d96f43a391c3f46c7b275fc0ef84c150146e7c5f41a74ceb71c1bfe",
"height": 8049520,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "84d29c92fe55112c6d33bfbfe0c3bcb56a6b27334fac1cbed6d2547c79348781",
"timestamp": "2022-04-11T12:02:35Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "f52f0a32a61b8927093426dcae2a51316c5cb4bf3904b433d6f939ec411b1458",
"height": 8049443,
"num_transactions": 1,
"size_limit": "22020096",
"state_root": "803ecc64252be86389c8551ae4bf6ec514b63a3f51740033ca8c4c18282c1d9b",
"timestamp": "2022-04-11T11:54:24Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "491c1acac829052f8f9bbb63dbcc79b90b5632898119b5af2d1058dd61bec6bc",
"height": 8049442,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "60553c7c68ff61f1be7bc4117536568afe55d69da2c7d0e1aeb90ed573f8000d",
"timestamp": "2022-04-11T11:54:14Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "429cb0e91327ee237776fc519630bc5321189dd90d3d7669d7c597adff3b95fa",
"height": 8049365,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "d7cd2e785fc19e0f7cf542fef935da7d017419e1294109f27c183a67acb1c464",
"timestamp": "2022-04-11T11:46:12Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "ef03561ea151f7d091be07cea46f05909763f3571d6758ab028a48a94a61c83b",
"height": 8049285,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "c046b5a4fa7ad9b69746ee709cfe298667d4db54c43ace51bf5562c23441d1bc",
"timestamp": "2022-04-11T11:37:34Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "17628866897d9426ef05a20d822bb79e6b0da748ad1e40e498213e8e3dd5d700",
"height": 8049214,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "de03f2ba514dde45e3997c8fd48a04703e873fb15623b6f8cce8c3ebc65daa21",
"timestamp": "2022-04-11T11:29:58Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "7a25a0f2abce3e14997ee8913ed0fc36b004765438e8a911e3ef20c68db38a12",
"height": 8049143,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "4e39f4809250b7e9f7cc8170bbcdfecd5939b6ebc2d3d65300e97559faed403b",
"timestamp": "2022-04-11T11:22:32Z"
},
{
"epoch": 13402,
"gas_limit": "0",
"hash": "e8e405b25518557eaf8c561a20ef699e8f3c7befd542b1bf20d5335a12d06c77",
"height": 8049061,
"num_transactions": 0,
"size_limit": "22020096",
"state_root": "ac4f911631004d0fd8eabe52d1263071e1f1e4deb35ef55f7ec8749a566dacf4",
"timestamp": "2022-04-11T11:13:22Z"
}
],
"is_total_count_clipped": false,
"total_count": 14
}
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
Transfer-Encoding: chunked

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 @@ -19,6 +19,7 @@ testCases=(
'tx /v1/consensus/transactions/f7a03e0912d355901ee794e5fec79a6b4c91363fc27d953596ee6de5c1492798'
'validator /v1/consensus/validators/oasis1qr3w66akc8ud9a4zsgyjw2muvcfjgfszn5ycgc0a'
'validator_history /v1/consensus/validators/oasis1qq0xmq7r0z9sdv02t5j9zs7en3n6574gtg8v9fyt/history'
'validator_proposed_blocks /v1/consensus/validators/oasis1qq0xmq7r0z9sdv02t5j9zs7en3n6574gtg8v9fyt/proposed_blocks'
'emerald_tx /v1/emerald/transactions/a6471a9c6f3307087586da9156f3c9876fbbaf4b23910cd9a2ac524a54d0aefe'
'emerald_failed_tx /v1/emerald/transactions/a7e76442c52a3cb81f719bde26c9a6179bd3415f96740d91a93ee8f205b45150'
'emerald_token_nfts /v1/emerald/evm_tokens/oasis1qqewaa87rnyshyqs7yutnnpzzetejecgeu005l8u/nfts'
Expand Down
Loading

0 comments on commit d6b4b43

Please sign in to comment.