github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/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/franono/tendermint/config"
    10  	"github.com/franono/tendermint/consensus"
    11  	"github.com/franono/tendermint/crypto"
    12  	"github.com/franono/tendermint/libs/log"
    13  	mempl "github.com/franono/tendermint/mempool"
    14  	"github.com/franono/tendermint/p2p"
    15  	"github.com/franono/tendermint/proxy"
    16  	sm "github.com/franono/tendermint/state"
    17  	"github.com/franono/tendermint/state/txindex"
    18  	"github.com/franono/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  
    72  	// interfaces defined in types and above
    73  	StateDB        dbm.DB
    74  	BlockStore     sm.BlockStore
    75  	EvidencePool   sm.EvidencePool
    76  	ConsensusState Consensus
    77  	P2PPeers       peers
    78  	P2PTransport   transport
    79  
    80  	// objects
    81  	PubKey           crypto.PubKey
    82  	GenDoc           *types.GenesisDoc // cache the genesis structure
    83  	TxIndexer        txindex.TxIndexer
    84  	ConsensusReactor *consensus.Reactor
    85  	EventBus         *types.EventBus // thread safe
    86  	Mempool          mempl.Mempool
    87  
    88  	Logger log.Logger
    89  
    90  	Config cfg.RPCConfig
    91  }
    92  
    93  //----------------------------------------------
    94  
    95  func validatePage(page, perPage, totalCount int) (int, error) {
    96  	if perPage < 1 {
    97  		panic(fmt.Sprintf("zero or negative perPage: %d", perPage))
    98  	}
    99  
   100  	if page == 0 {
   101  		return 1, nil // default
   102  	}
   103  
   104  	pages := ((totalCount - 1) / perPage) + 1
   105  	if pages == 0 {
   106  		pages = 1 // one page (even if it's empty)
   107  	}
   108  	if page < 0 || page > pages {
   109  		return 1, fmt.Errorf("page should be within [0, %d] range, given %d", pages, page)
   110  	}
   111  
   112  	return page, nil
   113  }
   114  
   115  func validatePerPage(perPage int) int {
   116  	if perPage < 1 {
   117  		return defaultPerPage
   118  	} else if perPage > maxPerPage {
   119  		return maxPerPage
   120  	}
   121  	return perPage
   122  }
   123  
   124  func validateSkipCount(page, perPage int) int {
   125  	skipCount := (page - 1) * perPage
   126  	if skipCount < 0 {
   127  		return 0
   128  	}
   129  
   130  	return skipCount
   131  }
   132  
   133  // latestHeight can be either latest committed or uncommitted (+1) height.
   134  func getHeight(latestHeight int64, heightPtr *int64) (int64, error) {
   135  	if heightPtr != nil {
   136  		height := *heightPtr
   137  		if height <= 0 {
   138  			return 0, fmt.Errorf("height must be greater than 0, but got %d", height)
   139  		}
   140  		if height > latestHeight {
   141  			return 0, fmt.Errorf("height %d must be less than or equal to the current blockchain height %d",
   142  				height, latestHeight)
   143  		}
   144  		base := env.BlockStore.Base()
   145  		if height < base {
   146  			return 0, fmt.Errorf("height %v is not available, blocks pruned at height %v",
   147  				height, base)
   148  		}
   149  		return height, nil
   150  	}
   151  	return latestHeight, nil
   152  }
   153  
   154  func latestUncommittedHeight() int64 {
   155  	nodeIsSyncing := env.ConsensusReactor.WaitSync()
   156  	if nodeIsSyncing {
   157  		return env.BlockStore.Height()
   158  	}
   159  	return env.BlockStore.Height() + 1
   160  }