github.com/soomindae/tendermint@v0.0.5-0.20210528140126-84a0c70c8162/rpc/core/env.go (about)

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