github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/rpc/core/env.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	cfg "github.com/lazyledger/lazyledger-core/config"
     8  	"github.com/lazyledger/lazyledger-core/consensus"
     9  	"github.com/lazyledger/lazyledger-core/crypto"
    10  	"github.com/lazyledger/lazyledger-core/libs/log"
    11  	mempl "github.com/lazyledger/lazyledger-core/mempool"
    12  	"github.com/lazyledger/lazyledger-core/p2p"
    13  	"github.com/lazyledger/lazyledger-core/proxy"
    14  	sm "github.com/lazyledger/lazyledger-core/state"
    15  	"github.com/lazyledger/lazyledger-core/state/txindex"
    16  	"github.com/lazyledger/lazyledger-core/types"
    17  )
    18  
    19  const (
    20  	// see README
    21  	defaultPerPage = 30
    22  	maxPerPage     = 100
    23  
    24  	// SubscribeTimeout is the maximum time we wait to subscribe for an event.
    25  	// must be less than the server's write timeout (see rpcserver.DefaultConfig)
    26  	SubscribeTimeout = 5 * time.Second
    27  )
    28  
    29  var (
    30  	// set by Node
    31  	env *Environment
    32  )
    33  
    34  // SetEnvironment sets up the given Environment.
    35  // It will race if multiple Node call SetEnvironment.
    36  func SetEnvironment(e *Environment) {
    37  	env = e
    38  }
    39  
    40  //----------------------------------------------
    41  // These interfaces are used by RPC and must be thread safe
    42  
    43  type Consensus interface {
    44  	GetState() sm.State
    45  	GetValidators() (int64, []*types.Validator)
    46  	GetLastHeight() int64
    47  	GetRoundStateJSON() ([]byte, error)
    48  	GetRoundStateSimpleJSON() ([]byte, error)
    49  }
    50  
    51  type transport interface {
    52  	Listeners() []string
    53  	IsListening() bool
    54  	NodeInfo() p2p.NodeInfo
    55  }
    56  
    57  type peers interface {
    58  	AddPersistentPeers([]string) error
    59  	AddUnconditionalPeerIDs([]string) error
    60  	AddPrivatePeerIDs([]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  	StateStore     sm.Store
    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, lowest height is %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  }