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 }