mirror of
https://github.com/tendermint/tendermint.git
synced 2026-07-20 15:02:33 +00:00
rpc: implement header and header_by_hash queries (#7270)
This commit is contained in:
committed by
GitHub
parent
f6c39126ed
commit
5f57d84dd3
@@ -39,6 +39,7 @@ Special thanks to external contributors on this release:
|
||||
|
||||
### FEATURES
|
||||
|
||||
- [rpc] [\#7270](https://github.com/tendermint/tendermint/pull/7270) Add `header` and `header_by_hash` RPC Client queries. (@fedekunze)
|
||||
- [cli] [#7033](https://github.com/tendermint/tendermint/pull/7033) Add a `rollback` command to rollback to the previous tendermint state in the event of non-determinstic app hash or reverting an upgrade.
|
||||
- [mempool, rpc] \#7041 Add removeTx operation to the RPC layer. (@tychoish)
|
||||
|
||||
|
||||
@@ -1241,6 +1241,7 @@ func (bs *mockBlockStore) LoadBlock(height int64) *types.Block { return bs.chain
|
||||
func (bs *mockBlockStore) LoadBlockByHash(hash []byte) *types.Block {
|
||||
return bs.chain[int64(len(bs.chain))-1]
|
||||
}
|
||||
func (bs *mockBlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { return nil }
|
||||
func (bs *mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
|
||||
block := bs.chain[height-1]
|
||||
return &types.BlockMeta{
|
||||
|
||||
@@ -51,7 +51,8 @@ func (env *Environment) BlockchainInfo(
|
||||
|
||||
return &coretypes.ResultBlockchainInfo{
|
||||
LastHeight: env.BlockStore.Height(),
|
||||
BlockMetas: blockMetas}, nil
|
||||
BlockMetas: blockMetas,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// error if either min or max are negative or min > max
|
||||
@@ -122,6 +123,38 @@ func (env *Environment) BlockByHash(ctx *rpctypes.Context, hash bytes.HexBytes)
|
||||
return &coretypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil
|
||||
}
|
||||
|
||||
// Header gets block header at a given height.
|
||||
// If no height is provided, it will fetch the latest header.
|
||||
// More: https://docs.tendermint.com/master/rpc/#/Info/header
|
||||
func (env *Environment) Header(ctx *rpctypes.Context, heightPtr *int64) (*coretypes.ResultHeader, error) {
|
||||
height, err := env.getHeight(env.BlockStore.Height(), heightPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockMeta := env.BlockStore.LoadBlockMeta(height)
|
||||
if blockMeta == nil {
|
||||
return &coretypes.ResultHeader{}, nil
|
||||
}
|
||||
|
||||
return &coretypes.ResultHeader{Header: &blockMeta.Header}, nil
|
||||
}
|
||||
|
||||
// HeaderByHash gets header by hash.
|
||||
// More: https://docs.tendermint.com/master/rpc/#/Info/header_by_hash
|
||||
func (env *Environment) HeaderByHash(ctx *rpctypes.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
|
||||
// N.B. The hash parameter is HexBytes so that the reflective parameter
|
||||
// decoding logic in the HTTP service will correctly translate from JSON.
|
||||
// See https://github.com/tendermint/tendermint/issues/6802 for context.
|
||||
|
||||
blockMeta := env.BlockStore.LoadBlockMetaByHash(hash)
|
||||
if blockMeta == nil {
|
||||
return &coretypes.ResultHeader{}, nil
|
||||
}
|
||||
|
||||
return &coretypes.ResultHeader{Header: &blockMeta.Header}, nil
|
||||
}
|
||||
|
||||
// Commit gets block commit at a given height.
|
||||
// If no height is provided, it will fetch the commit for the latest block.
|
||||
// More: https://docs.tendermint.com/master/rpc/#/Info/commit
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
sm "github.com/tendermint/tendermint/internal/state"
|
||||
"github.com/tendermint/tendermint/internal/state/mocks"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
"github.com/tendermint/tendermint/rpc/coretypes"
|
||||
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func TestBlockchainInfo(t *testing.T) {
|
||||
@@ -84,7 +84,10 @@ func TestBlockResults(t *testing.T) {
|
||||
env.StateStore = sm.NewStore(dbm.NewMemDB())
|
||||
err := env.StateStore.SaveABCIResponses(100, results)
|
||||
require.NoError(t, err)
|
||||
env.BlockStore = mockBlockStore{height: 100}
|
||||
mockstore := &mocks.BlockStore{}
|
||||
mockstore.On("Height").Return(int64(100))
|
||||
mockstore.On("Base").Return(int64(1))
|
||||
env.BlockStore = mockstore
|
||||
|
||||
testCases := []struct {
|
||||
height int64
|
||||
@@ -115,21 +118,3 @@ func TestBlockResults(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type mockBlockStore struct {
|
||||
height int64
|
||||
}
|
||||
|
||||
func (mockBlockStore) Base() int64 { return 1 }
|
||||
func (store mockBlockStore) Height() int64 { return store.height }
|
||||
func (store mockBlockStore) Size() int64 { return store.height }
|
||||
func (mockBlockStore) LoadBaseMeta() *types.BlockMeta { return nil }
|
||||
func (mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta { return nil }
|
||||
func (mockBlockStore) LoadBlock(height int64) *types.Block { return nil }
|
||||
func (mockBlockStore) LoadBlockByHash(hash []byte) *types.Block { return nil }
|
||||
func (mockBlockStore) LoadBlockPart(height int64, index int) *types.Part { return nil }
|
||||
func (mockBlockStore) LoadBlockCommit(height int64) *types.Commit { return nil }
|
||||
func (mockBlockStore) LoadSeenCommit() *types.Commit { return nil }
|
||||
func (mockBlockStore) PruneBlocks(height int64) (uint64, error) { return 0, nil }
|
||||
func (mockBlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) {
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ func (env *Environment) GetRoutes() RoutesMap {
|
||||
"blockchain": rpc.NewRPCFunc(env.BlockchainInfo, "minHeight,maxHeight", true),
|
||||
"genesis": rpc.NewRPCFunc(env.Genesis, "", true),
|
||||
"genesis_chunked": rpc.NewRPCFunc(env.GenesisChunked, "chunk", true),
|
||||
"header": rpc.NewRPCFunc(env.Header, "height", true),
|
||||
"header_by_hash": rpc.NewRPCFunc(env.HeaderByHash, "hash", true),
|
||||
"block": rpc.NewRPCFunc(env.Block, "height", true),
|
||||
"block_by_hash": rpc.NewRPCFunc(env.BlockByHash, "hash", true),
|
||||
"block_results": rpc.NewRPCFunc(env.BlockResults, "height", true),
|
||||
|
||||
@@ -121,6 +121,22 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockMetaByHash provides a mock function with given fields: hash
|
||||
func (_m *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta {
|
||||
ret := _m.Called(hash)
|
||||
|
||||
var r0 *types.BlockMeta
|
||||
if rf, ok := ret.Get(0).(func([]byte) *types.BlockMeta); ok {
|
||||
r0 = rf(hash)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.BlockMeta)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockPart provides a mock function with given fields: height, index
|
||||
func (_m *BlockStore) LoadBlockPart(height int64, index int) *types.Part {
|
||||
ret := _m.Called(height, index)
|
||||
|
||||
@@ -29,6 +29,7 @@ type BlockStore interface {
|
||||
PruneBlocks(height int64) (uint64, error)
|
||||
|
||||
LoadBlockByHash(hash []byte) *types.Block
|
||||
LoadBlockMetaByHash(hash []byte) *types.BlockMeta
|
||||
LoadBlockPart(height int64, index int) *types.Part
|
||||
|
||||
LoadBlockCommit(height int64) *types.Commit
|
||||
|
||||
@@ -181,6 +181,26 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) *types.Block {
|
||||
return bs.LoadBlock(height)
|
||||
}
|
||||
|
||||
// LoadBlockMetaByHash returns the blockmeta who's header corresponds to the given
|
||||
// hash. If none is found, returns nil.
|
||||
func (bs *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta {
|
||||
bz, err := bs.db.Get(blockHashKey(hash))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
s := string(bz)
|
||||
height, err := strconv.ParseInt(s, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to extract height from %s: %v", s, err))
|
||||
}
|
||||
return bs.LoadBlockMeta(height)
|
||||
}
|
||||
|
||||
// LoadBlockPart returns the Part at the given index
|
||||
// from the block at the given height.
|
||||
// If no part is found for the given height and index, it returns nil.
|
||||
|
||||
@@ -24,6 +24,8 @@ func RPCRoutes(c *lrpc.Client) map[string]*rpcserver.RPCFunc {
|
||||
"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight", true),
|
||||
"genesis": rpcserver.NewRPCFunc(makeGenesisFunc(c), "", true),
|
||||
"genesis_chunked": rpcserver.NewRPCFunc(makeGenesisChunkedFunc(c), "", true),
|
||||
"header": rpcserver.NewRPCFunc(makeHeaderFunc(c), "height", true),
|
||||
"header_by_hash": rpcserver.NewRPCFunc(makeHeaderByHashFunc(c), "hash", true),
|
||||
"block": rpcserver.NewRPCFunc(makeBlockFunc(c), "height", true),
|
||||
"block_by_hash": rpcserver.NewRPCFunc(makeBlockByHashFunc(c), "hash", true),
|
||||
"block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height", true),
|
||||
@@ -101,6 +103,22 @@ func makeGenesisChunkedFunc(c *lrpc.Client) rpcGenesisChunkedFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type rpcHeaderFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultHeader, error)
|
||||
|
||||
func makeHeaderFunc(c *lrpc.Client) rpcHeaderFunc {
|
||||
return func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultHeader, error) {
|
||||
return c.Header(ctx.Context(), height)
|
||||
}
|
||||
}
|
||||
|
||||
type rpcHeaderByHashFunc func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultHeader, error)
|
||||
|
||||
func makeHeaderByHashFunc(c *lrpc.Client) rpcHeaderByHashFunc {
|
||||
return func(ctx *rpctypes.Context, hash []byte) (*coretypes.ResultHeader, error) {
|
||||
return c.HeaderByHash(ctx.Context(), hash)
|
||||
}
|
||||
}
|
||||
|
||||
type rpcBlockFunc func(ctx *rpctypes.Context, height *int64) (*coretypes.ResultBlock, error)
|
||||
|
||||
func makeBlockFunc(c *lrpc.Client) rpcBlockFunc {
|
||||
|
||||
+36
-1
@@ -451,6 +451,40 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.Re
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Header fetches and verifies the header directly via the light client
|
||||
func (c *Client) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
|
||||
lb, err := c.updateLightClientIfNeededTo(ctx, height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &coretypes.ResultHeader{Header: lb.Header}, nil
|
||||
}
|
||||
|
||||
// HeaderByHash calls rpcclient#HeaderByHash and updates the client if it's falling behind.
|
||||
func (c *Client) HeaderByHash(ctx context.Context, hash tmbytes.HexBytes) (*coretypes.ResultHeader, error) {
|
||||
res, err := c.next.HeaderByHash(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := res.Header.ValidateBasic(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lb, err := c.updateLightClientIfNeededTo(ctx, &res.Header.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !bytes.Equal(lb.Header.Hash(), res.Header.Hash()) {
|
||||
return nil, fmt.Errorf("primary header hash does not match trusted header hash. (%X != %X)",
|
||||
lb.Header.Hash(), res.Header.Hash())
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
|
||||
// Update the light client if we're behind and retrieve the light block at the requested height
|
||||
// or at the latest height if no height is provided.
|
||||
@@ -535,7 +569,8 @@ func (c *Client) Validators(
|
||||
BlockHeight: l.Height,
|
||||
Validators: v,
|
||||
Count: len(v),
|
||||
Total: totalCount}, nil
|
||||
Total: totalCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
|
||||
|
||||
+30
-3
@@ -92,9 +92,11 @@ type baseRPCClient struct {
|
||||
caller jsonrpcclient.Caller
|
||||
}
|
||||
|
||||
var _ rpcClient = (*HTTP)(nil)
|
||||
var _ rpcClient = (*BatchHTTP)(nil)
|
||||
var _ rpcClient = (*baseRPCClient)(nil)
|
||||
var (
|
||||
_ rpcClient = (*HTTP)(nil)
|
||||
_ rpcClient = (*BatchHTTP)(nil)
|
||||
_ rpcClient = (*baseRPCClient)(nil)
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HTTP
|
||||
@@ -450,6 +452,31 @@ func (c *baseRPCClient) BlockResults(
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *baseRPCClient) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
|
||||
result := new(coretypes.ResultHeader)
|
||||
params := make(map[string]interface{})
|
||||
if height != nil {
|
||||
params["height"] = height
|
||||
}
|
||||
_, err := c.caller.Call(ctx, "header", params, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *baseRPCClient) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
|
||||
result := new(coretypes.ResultHeader)
|
||||
params := map[string]interface{}{
|
||||
"hash": hash,
|
||||
}
|
||||
_, err := c.caller.Call(ctx, "header_by_hash", params, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
|
||||
result := new(coretypes.ResultCommit)
|
||||
params := make(map[string]interface{})
|
||||
|
||||
@@ -78,6 +78,8 @@ type SignClient interface {
|
||||
Block(ctx context.Context, height *int64) (*coretypes.ResultBlock, error)
|
||||
BlockByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultBlock, error)
|
||||
BlockResults(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error)
|
||||
Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error)
|
||||
HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error)
|
||||
Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error)
|
||||
Validators(ctx context.Context, height *int64, page, perPage *int) (*coretypes.ResultValidators, error)
|
||||
Tx(ctx context.Context, hash bytes.HexBytes, prove bool) (*coretypes.ResultTx, error)
|
||||
|
||||
@@ -165,6 +165,14 @@ func (c *Local) BlockResults(ctx context.Context, height *int64) (*coretypes.Res
|
||||
return c.env.BlockResults(c.ctx, height)
|
||||
}
|
||||
|
||||
func (c *Local) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
|
||||
return c.env.Header(c.ctx, height)
|
||||
}
|
||||
|
||||
func (c *Local) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
|
||||
return c.env.HeaderByHash(c.ctx, hash)
|
||||
}
|
||||
|
||||
func (c *Local) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
|
||||
return c.env.Commit(c.ctx, height)
|
||||
}
|
||||
|
||||
@@ -457,6 +457,52 @@ func (_m *Client) GenesisChunked(_a0 context.Context, _a1 uint) (*coretypes.Resu
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Header provides a mock function with given fields: ctx, height
|
||||
func (_m *Client) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
|
||||
ret := _m.Called(ctx, height)
|
||||
|
||||
var r0 *coretypes.ResultHeader
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultHeader); ok {
|
||||
r0 = rf(ctx, height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*coretypes.ResultHeader)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok {
|
||||
r1 = rf(ctx, height)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// HeaderByHash provides a mock function with given fields: ctx, hash
|
||||
func (_m *Client) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
|
||||
ret := _m.Called(ctx, hash)
|
||||
|
||||
var r0 *coretypes.ResultHeader
|
||||
if rf, ok := ret.Get(0).(func(context.Context, bytes.HexBytes) *coretypes.ResultHeader); ok {
|
||||
r0 = rf(ctx, hash)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*coretypes.ResultHeader)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, bytes.HexBytes) error); ok {
|
||||
r1 = rf(ctx, hash)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Health provides a mock function with given fields: _a0
|
||||
func (_m *Client) Health(_a0 context.Context) (*coretypes.ResultHealth, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
@@ -359,6 +359,15 @@ func TestClientMethodCalls(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, block, blockByHash)
|
||||
|
||||
// check that the header matches the block hash
|
||||
header, err := c.Header(ctx, &apph)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, block.Block.Header, *header.Header)
|
||||
|
||||
headerByHash, err := c.HeaderByHash(ctx, block.BlockID.Hash)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, header, headerByHash)
|
||||
|
||||
// now check the results
|
||||
blockResults, err := c.BlockResults(ctx, &txh)
|
||||
require.NoError(t, err, "%d: %+v", i, err)
|
||||
@@ -551,7 +560,6 @@ func TestClientMethodCalls(t *testing.T) {
|
||||
_, err := c.BroadcastEvidence(ctx, fake)
|
||||
require.Error(t, err, "BroadcastEvidence(%s) succeeded, but the evidence was fake", fake)
|
||||
}
|
||||
|
||||
})
|
||||
t.Run("BroadcastEmpty", func(t *testing.T) {
|
||||
_, err := c.BroadcastEvidence(ctx, nil)
|
||||
@@ -732,7 +740,6 @@ func TestClientMethodCallsAdvanced(t *testing.T) {
|
||||
|
||||
for _, c := range GetClients(t, n, conf) {
|
||||
t.Run(fmt.Sprintf("%T", c), func(t *testing.T) {
|
||||
|
||||
// now we query for the tx.
|
||||
result, err := c.TxSearch(ctx, fmt.Sprintf("tx.hash='%v'", find.Hash), true, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -51,6 +51,11 @@ type ResultBlock struct {
|
||||
Block *types.Block `json:"block"`
|
||||
}
|
||||
|
||||
// ResultHeader represents the response for a Header RPC Client query
|
||||
type ResultHeader struct {
|
||||
Header *types.Header `json:"header"`
|
||||
}
|
||||
|
||||
// Commit and Header
|
||||
type ResultCommit struct {
|
||||
types.SignedHeader `json:"signed_header"`
|
||||
|
||||
@@ -525,7 +525,7 @@ paths:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/net_info:
|
||||
get:
|
||||
summary: Network informations
|
||||
summary: Network information
|
||||
operationId: net_info
|
||||
tags:
|
||||
- Info
|
||||
@@ -693,6 +693,64 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/header:
|
||||
get:
|
||||
summary: Get the header at a specified height
|
||||
operationId: header
|
||||
parameters:
|
||||
- in: query
|
||||
name: height
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
example: 1
|
||||
description: height to return. If no height is provided, it will fetch the latest height.
|
||||
tags:
|
||||
- Info
|
||||
description: |
|
||||
Retrieve the block header corresponding to a specified height.
|
||||
responses:
|
||||
"200":
|
||||
description: Header information.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HeaderResponse"
|
||||
"500":
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/header_by_hash:
|
||||
get:
|
||||
summary: Get header by hash
|
||||
operationId: header_by_hash
|
||||
parameters:
|
||||
- in: query
|
||||
name: hash
|
||||
description: header hash
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
example: "0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED"
|
||||
tags:
|
||||
- Info
|
||||
description: |
|
||||
Retrieve the block header corresponding to a block hash.
|
||||
responses:
|
||||
"200":
|
||||
description: Header information.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HeaderResponse"
|
||||
"500":
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/block:
|
||||
get:
|
||||
summary: Get block at a specified height
|
||||
@@ -711,7 +769,7 @@ paths:
|
||||
Get Block.
|
||||
responses:
|
||||
"200":
|
||||
description: Block informations.
|
||||
description: Block information.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -740,7 +798,7 @@ paths:
|
||||
Get Block By Hash.
|
||||
responses:
|
||||
"200":
|
||||
description: Block informations.
|
||||
description: Block information.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -758,7 +816,7 @@ paths:
|
||||
parameters:
|
||||
- in: query
|
||||
name: height
|
||||
description: height to return. If no height is provided, it will fetch informations regarding the latest block.
|
||||
description: height to return. If no height is provided, it will fetch information regarding the latest block.
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
@@ -787,7 +845,7 @@ paths:
|
||||
parameters:
|
||||
- in: query
|
||||
name: height
|
||||
description: height to return. If no height is provided, it will fetch commit informations regarding the latest block.
|
||||
description: height to return. If no height is provided, it will fetch commit information regarding the latest block.
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
@@ -968,7 +1026,7 @@ paths:
|
||||
parameters:
|
||||
- in: query
|
||||
name: height
|
||||
description: height to return. If no height is provided, it will fetch commit informations regarding the latest block.
|
||||
description: height to return. If no height is provided, it will fetch commit information regarding the latest block.
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
@@ -1703,13 +1761,21 @@ components:
|
||||
block:
|
||||
$ref: "#/components/schemas/Block"
|
||||
BlockResponse:
|
||||
description: Blockc info
|
||||
description: Block info
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/JSONRPC"
|
||||
- type: object
|
||||
properties:
|
||||
result:
|
||||
$ref: "#/components/schemas/BlockComplete"
|
||||
HeaderResponse:
|
||||
description: Block Header info
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/JSONRPC"
|
||||
- type: object
|
||||
properties:
|
||||
result:
|
||||
$ref: "#/components/schemas/BlockHeader"
|
||||
|
||||
################## FROM NOW ON NEEDS REFACTOR ##################
|
||||
BlockResultsResponse:
|
||||
|
||||
Reference in New Issue
Block a user