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 }