mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-06 21:36:26 +00:00
rpc: add method block_by_hash (#4257)
* added RPC method block_by_hash * created hash => height * changes typings * block_by_hash changes * Update store/store.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update store/store.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update store/store.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update store/store.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> Co-authored-by: Marko <marbar3778@yahoo.com> Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
This commit is contained in:
committed by
Anton Kaliaev
parent
55410593d0
commit
7be74c73b7
@@ -113,6 +113,7 @@ program](https://hackerone.com/tendermint).
|
||||
- [cli] \#4234 Add `--db_backend and --db_dir` flags (@princesinha19)
|
||||
- [cli] \#4113 Add optional `--genesis_hash` flag to check genesis hash upon startup
|
||||
- [config] \#3831 Add support for [RocksDB](https://rocksdb.org/) (@Stumble)
|
||||
- [rpc] \#3985 Add new `/block_by_hash` endpoint, which allows to fetch a block by its hash (@princesinha19)
|
||||
- [metrics] \#4263 Add
|
||||
- `consensus_validator_power`: track your validators power
|
||||
- `consensus_validator_last_signed_height`: track at which height the validator last signed
|
||||
|
||||
@@ -1062,6 +1062,9 @@ func newMockBlockStore(config *cfg.Config, params types.ConsensusParams) *mockBl
|
||||
|
||||
func (bs *mockBlockStore) Height() int64 { return int64(len(bs.chain)) }
|
||||
func (bs *mockBlockStore) LoadBlock(height int64) *types.Block { return bs.chain[height-1] }
|
||||
func (bs *mockBlockStore) LoadBlockByHash(hash []byte) *types.Block {
|
||||
return bs.chain[int64(len(bs.chain))-1]
|
||||
}
|
||||
func (bs *mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
|
||||
block := bs.chain[height-1]
|
||||
return &types.BlockMeta{
|
||||
|
||||
@@ -81,6 +81,16 @@ func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error)
|
||||
return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil
|
||||
}
|
||||
|
||||
// BlockByHash gets block by hash.
|
||||
// More: https://tendermint.com/rpc/#/Info/block_by_hash
|
||||
func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) {
|
||||
block := blockStore.LoadBlockByHash(hash)
|
||||
height := block.Height
|
||||
|
||||
blockMeta := blockStore.LoadBlockMeta(height)
|
||||
return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, 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://tendermint.com/rpc/#/Info/commit
|
||||
|
||||
@@ -114,6 +114,7 @@ type mockBlockStore struct {
|
||||
func (store mockBlockStore) Height() int64 { return store.height }
|
||||
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(height int64) *types.Commit { return nil }
|
||||
|
||||
@@ -19,6 +19,7 @@ var Routes = map[string]*rpc.RPCFunc{
|
||||
"blockchain": rpc.NewRPCFunc(BlockchainInfo, "minHeight,maxHeight"),
|
||||
"genesis": rpc.NewRPCFunc(Genesis, ""),
|
||||
"block": rpc.NewRPCFunc(Block, "height"),
|
||||
"block_by_hash": rpc.NewRPCFunc(BlockByHash, "hash"),
|
||||
"block_results": rpc.NewRPCFunc(BlockResults, "height"),
|
||||
"commit": rpc.NewRPCFunc(Commit, "height"),
|
||||
"tx": rpc.NewRPCFunc(Tx, "hash,prove"),
|
||||
|
||||
@@ -550,6 +550,35 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/block_by_hash:
|
||||
get:
|
||||
summary: Get block by hash
|
||||
operationId: block_by_hash
|
||||
parameters:
|
||||
- in: query
|
||||
name: hash
|
||||
description: block hash
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
example: "0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED"
|
||||
tags:
|
||||
- Info
|
||||
description: |
|
||||
Get Block By Hash.
|
||||
responses:
|
||||
200:
|
||||
description: Block informations.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BlockResponse"
|
||||
500:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
/block_results:
|
||||
get:
|
||||
summary: Get block results at a specified height
|
||||
|
||||
@@ -18,6 +18,7 @@ type BlockStoreRPC interface {
|
||||
|
||||
LoadBlockMeta(height int64) *types.BlockMeta
|
||||
LoadBlock(height int64) *types.Block
|
||||
LoadBlockByHash(hash []byte) *types.Block
|
||||
LoadBlockPart(height int64, index int) *types.Part
|
||||
|
||||
LoadBlockCommit(height int64) *types.Commit
|
||||
|
||||
@@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -73,6 +74,24 @@ func (bs *BlockStore) LoadBlock(height int64) *types.Block {
|
||||
return block
|
||||
}
|
||||
|
||||
// LoadBlockByHash returns the block with the given hash.
|
||||
// If no block is found for that hash, it returns nil.
|
||||
// Panics if it fails to parse height associated with the given hash.
|
||||
func (bs *BlockStore) LoadBlockByHash(hash []byte) *types.Block {
|
||||
bz := bs.db.Get(calcBlockHashKey(hash))
|
||||
if len(bz) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
s := string(bz)
|
||||
height, err := strconv.ParseInt(s, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
panic(errors.Wrapf(err, "failed to extract height from %s", s))
|
||||
}
|
||||
return bs.LoadBlock(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.
|
||||
@@ -147,7 +166,10 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s
|
||||
if block == nil {
|
||||
panic("BlockStore can only save a non-nil block")
|
||||
}
|
||||
|
||||
height := block.Height
|
||||
hash := block.Hash()
|
||||
|
||||
if g, w := height, bs.Height()+1; g != w {
|
||||
panic(fmt.Sprintf("BlockStore can only save contiguous blocks. Wanted %v, got %v", w, g))
|
||||
}
|
||||
@@ -159,6 +181,7 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s
|
||||
blockMeta := types.NewBlockMeta(block, blockParts)
|
||||
metaBytes := cdc.MustMarshalBinaryBare(blockMeta)
|
||||
bs.db.Set(calcBlockMetaKey(height), metaBytes)
|
||||
bs.db.Set(calcBlockHashKey(hash), []byte(fmt.Sprintf("%d", height)))
|
||||
|
||||
// Save block parts
|
||||
for i := 0; i < blockParts.Total(); i++ {
|
||||
@@ -213,6 +236,10 @@ func calcSeenCommitKey(height int64) []byte {
|
||||
return []byte(fmt.Sprintf("SC:%v", height))
|
||||
}
|
||||
|
||||
func calcBlockHashKey(hash []byte) []byte {
|
||||
return []byte(fmt.Sprintf("BH:%x", hash))
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
var blockStoreKey = []byte("blockStore")
|
||||
|
||||
Reference in New Issue
Block a user