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  }