github.com/516108736/tendermint@v0.36.0/rpc/core/blocks.go (about) 1 package core 2 3 import ( 4 "fmt" 5 6 tmmath "github.com/tendermint/tendermint/libs/math" 7 ctypes "github.com/tendermint/tendermint/rpc/core/types" 8 rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" 9 "github.com/tendermint/tendermint/types" 10 ) 11 12 // BlockchainInfo gets block headers for minHeight <= height <= maxHeight. 13 // Block headers are returned in descending order (highest first). 14 // More: https://docs.tendermint.com/master/rpc/#/Info/blockchain 15 func BlockchainInfo(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { 16 // maximum 20 block metas 17 const limit int64 = 20 18 var err error 19 minHeight, maxHeight, err = filterMinMax( 20 env.BlockStore.Base(), 21 env.BlockStore.Height(), 22 minHeight, 23 maxHeight, 24 limit) 25 if err != nil { 26 return nil, err 27 } 28 env.Logger.Debug("BlockchainInfoHandler", "maxHeight", maxHeight, "minHeight", minHeight) 29 30 blockMetas := []*types.BlockMeta{} 31 for height := maxHeight; height >= minHeight; height-- { 32 blockMeta := env.BlockStore.LoadBlockMeta(height) 33 blockMetas = append(blockMetas, blockMeta) 34 } 35 36 return &ctypes.ResultBlockchainInfo{ 37 LastHeight: env.BlockStore.Height(), 38 BlockMetas: blockMetas}, nil 39 } 40 41 // error if either min or max are negative or min > max 42 // if 0, use blockstore base for min, latest block height for max 43 // enforce limit. 44 func filterMinMax(base, height, min, max, limit int64) (int64, int64, error) { 45 // filter negatives 46 if min < 0 || max < 0 { 47 return min, max, fmt.Errorf("heights must be non-negative") 48 } 49 50 // adjust for default values 51 if min == 0 { 52 min = 1 53 } 54 if max == 0 { 55 max = height 56 } 57 58 // limit max to the height 59 max = tmmath.MinInt64(height, max) 60 61 // limit min to the base 62 min = tmmath.MaxInt64(base, min) 63 64 // limit min to within `limit` of max 65 // so the total number of blocks returned will be `limit` 66 min = tmmath.MaxInt64(min, max-limit+1) 67 68 if min > max { 69 return min, max, fmt.Errorf("min height %d can't be greater than max height %d", min, max) 70 } 71 return min, max, nil 72 } 73 74 // Block gets block at a given height. 75 // If no height is provided, it will fetch the latest block. 76 // More: https://docs.tendermint.com/master/rpc/#/Info/block 77 func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) { 78 height, err := getHeight(env.BlockStore.Height(), heightPtr) 79 if err != nil { 80 return nil, err 81 } 82 83 block := env.BlockStore.LoadBlock(height) 84 blockMeta := env.BlockStore.LoadBlockMeta(height) 85 if blockMeta == nil { 86 return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: block}, nil 87 } 88 return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil 89 } 90 91 // BlockByHash gets block by hash. 92 // More: https://docs.tendermint.com/master/rpc/#/Info/block_by_hash 93 func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) { 94 block := env.BlockStore.LoadBlockByHash(hash) 95 if block == nil { 96 return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: nil}, nil 97 } 98 // If block is not nil, then blockMeta can't be nil. 99 blockMeta := env.BlockStore.LoadBlockMeta(block.Height) 100 return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil 101 } 102 103 // Commit gets block commit at a given height. 104 // If no height is provided, it will fetch the commit for the latest block. 105 // More: https://docs.tendermint.com/master/rpc/#/Info/commit 106 func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, error) { 107 height, err := getHeight(env.BlockStore.Height(), heightPtr) 108 if err != nil { 109 return nil, err 110 } 111 112 blockMeta := env.BlockStore.LoadBlockMeta(height) 113 if blockMeta == nil { 114 return nil, nil 115 } 116 header := blockMeta.Header 117 118 // If the next block has not been committed yet, 119 // use a non-canonical commit 120 if height == env.BlockStore.Height() { 121 commit := env.BlockStore.LoadSeenCommit(height) 122 return ctypes.NewResultCommit(&header, commit, false), nil 123 } 124 125 // Return the canonical commit (comes from the block at height+1) 126 commit := env.BlockStore.LoadBlockCommit(height) 127 return ctypes.NewResultCommit(&header, commit, true), nil 128 } 129 130 // BlockResults gets ABCIResults at a given height. 131 // If no height is provided, it will fetch results for the latest block. 132 // 133 // Results are for the height of the block containing the txs. 134 // Thus response.results.deliver_tx[5] is the results of executing 135 // getBlock(h).Txs[5] 136 // More: https://docs.tendermint.com/master/rpc/#/Info/block_results 137 func BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockResults, error) { 138 height, err := getHeight(env.BlockStore.Height(), heightPtr) 139 if err != nil { 140 return nil, err 141 } 142 143 results, err := env.StateStore.LoadABCIResponses(height) 144 if err != nil { 145 return nil, err 146 } 147 148 return &ctypes.ResultBlockResults{ 149 Height: height, 150 TxsResults: results.DeliverTxs, 151 BeginBlockEvents: results.BeginBlock.Events, 152 EndBlockEvents: results.EndBlock.Events, 153 ValidatorUpdates: results.EndBlock.ValidatorUpdates, 154 ConsensusParamUpdates: results.EndBlock.ConsensusParamUpdates, 155 }, nil 156 }