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