github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/rpc/core/env.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	dbm "github.com/tendermint/tm-db"
     8  
     9  	cfg "github.com/tendermint/tendermint/config"
    10  	"github.com/tendermint/tendermint/consensus"
    11  	"github.com/tendermint/tendermint/crypto"
    12  	"github.com/tendermint/tendermint/libs/log"
    13  	mempl "github.com/tendermint/tendermint/mempool"
    14  	"github.com/tendermint/tendermint/p2p"
    15  	"github.com/tendermint/tendermint/proxy"
    16  	sm "github.com/tendermint/tendermint/state"
    17  	"github.com/tendermint/tendermint/state/txindex"
    18  	"github.com/tendermint/tendermint/types"
    19  )
    20  
    21  const (
    22  	// see README
    23  	defaultPerPage = 30
    24  	maxPerPage     = 100
    25  
    26  	// SubscribeTimeout is the maximum time we wait to subscribe for an event.
    27  	// must be less than the server's write timeout (see rpcserver.DefaultConfig)
    28  	SubscribeTimeout = 5 * time.Second
    29  )
    30  
    31  var (
    32  	// set by Node
    33  	env *Environment
    34  )
    35  
    36  // SetEnvironment sets up the given Environment.
    37  // It will race if multiple Node call SetEnvironment.
    38  func SetEnvironment(e *Environment) {
    39  	env = e
    40  }
    41  
    42  //----------------------------------------------
    43  // These interfaces are used by RPC and must be thread safe
    44  
    45  type Consensus interface {
    46  	GetState() sm.State
    47  	GetValidators() (int64, []*types.Validator)
    48  	GetLastHeight() int64
    49  	GetRoundStateJSON() ([]byte, error)
    50  	GetRoundStateSimpleJSON() ([]byte, error)
    51  }
    52  
    53  type transport interface {
    54  	Listeners() []string
    55  	IsListening() bool
    56  	NodeInfo() p2p.NodeInfo
    57  }
    58  
    59  type peers interface {
    60  	AddPersistentPeers([]string) error
    61  	DialPeersAsync([]string) error
    62  	Peers() p2p.IPeerSet
    63  }
    64  
    65  //----------------------------------------------
    66  // Environment contains objects and interfaces used by the RPC. It is expected
    67  // to be setup once during startup.
    68  type Environment struct {
    69  	// external, thread safe interfaces
    70  	ProxyAppQuery   proxy.AppConnQuery
    71  	ProxyAppMempool proxy.AppConnMempool
    72  
    73  	// interfaces defined in types and above
    74  	StateDB        dbm.DB
    75  	BlockStore     sm.BlockStore
    76  	EvidencePool   sm.EvidencePool
    77  	ConsensusState Consensus
    78  	P2PPeers       peers
    79  	P2PTransport   transport
    80  
    81  	// objects
    82  	PubKey           crypto.PubKey
    83  	GenDoc           *types.GenesisDoc // cache the genesis structure
    84  	TxIndexer        txindex.TxIndexer
    85  	ConsensusReactor *consensus.Reactor
    86  	EventBus         *types.EventBus // thread safe
    87  	Mempool          mempl.Mempool
    88  
    89  	Logger log.Logger
    90  
    91  	Config cfg.RPCConfig
    92  }
    93  
    94  //----------------------------------------------
    95  
    96  func validatePage(pagePtr *int, perPage, totalCount int) (int, error) {
    97  	if perPage < 1 {
    98  		panic(fmt.Sprintf("zero or negative perPage: %d", perPage))
    99  	}
   100  
   101  	if pagePtr == nil { // no page parameter
   102  		return 1, nil
   103  	}
   104  
   105  	pages := ((totalCount - 1) / perPage) + 1
   106  	if pages == 0 {
   107  		pages = 1 // one page (even if it's empty)
   108  	}
   109  	page := *pagePtr
   110  	if page <= 0 || page > pages {
   111  		return 1, fmt.Errorf("page should be within [1, %d] range, given %d", pages, page)
   112  	}
   113  
   114  	return page, nil
   115  }
   116  
   117  func validatePerPage(perPagePtr *int) int {
   118  	if perPagePtr == nil { // no per_page parameter
   119  		return defaultPerPage
   120  	}
   121  
   122  	perPage := *perPagePtr
   123  	if perPage < 1 {
   124  		return defaultPerPage
   125  	} else if perPage > maxPerPage {
   126  		return maxPerPage
   127  	}
   128  	return perPage
   129  }
   130  
   131  func validateSkipCount(page, perPage int) int {
   132  	skipCount := (page - 1) * perPage
   133  	if skipCount < 0 {
   134  		return 0
   135  	}
   136  
   137  	return skipCount
   138  }
   139  
   140  // latestHeight can be either latest committed or uncommitted (+1) height.
   141  func getHeight(latestHeight int64, heightPtr *int64) (int64, error) {
   142  	if heightPtr != nil {
   143  		height := *heightPtr
   144  		if height <= 0 {
   145  			return 0, fmt.Errorf("height must be greater than 0, but got %d", height)
   146  		}
   147  		if height > latestHeight {
   148  			return 0, fmt.Errorf("height %d must be less than or equal to the current blockchain height %d",
   149  				height, latestHeight)
   150  		}
   151  		base := env.BlockStore.Base()
   152  		if height < base {
   153  			return 0, fmt.Errorf("height %v is not available, blocks pruned at height %v",
   154  				height, base)
   155  		}
   156  		return height, nil
   157  	}
   158  	return latestHeight, nil
   159  }
   160  
   161  func latestUncommittedHeight() int64 {
   162  	nodeIsSyncing := env.ConsensusReactor.WaitSync()
   163  	if nodeIsSyncing {
   164  		return env.BlockStore.Height()
   165  	}
   166  	return env.BlockStore.Height() + 1
   167  }