You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
6.7 KiB

limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
7 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
  1. package core
  2. import (
  3. "fmt"
  4. cmn "github.com/tendermint/tendermint/libs/common"
  5. tmquery "github.com/tendermint/tendermint/libs/pubsub/query"
  6. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  7. rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
  8. "github.com/tendermint/tendermint/state/txindex/null"
  9. "github.com/tendermint/tendermint/types"
  10. )
  11. // Tx allows you to query the transaction results. `nil` could mean the
  12. // transaction is in the mempool, invalidated, or was not sent in the first
  13. // place.
  14. //
  15. // ```shell
  16. // curl "localhost:26657/tx?hash=0xF87370F68C82D9AC7201248ECA48CEC5F16FFEC99C461C1B2961341A2FE9C1C8"
  17. // ```
  18. //
  19. // ```go
  20. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  21. // err := client.Start()
  22. // if err != nil {
  23. // // handle error
  24. // }
  25. // defer client.Stop()
  26. // hashBytes, err := hex.DecodeString("F87370F68C82D9AC7201248ECA48CEC5F16FFEC99C461C1B2961341A2FE9C1C8")
  27. // tx, err := client.Tx(hashBytes, true)
  28. // ```
  29. //
  30. // > The above command returns JSON structured like this:
  31. //
  32. // ```json
  33. // {
  34. // "error": "",
  35. // "result": {
  36. // "proof": {
  37. // "Proof": {
  38. // "aunts": []
  39. // },
  40. // "Data": "YWJjZA==",
  41. // "RootHash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF",
  42. // "Total": "1",
  43. // "Index": "0"
  44. // },
  45. // "tx": "YWJjZA==",
  46. // "tx_result": {
  47. // "log": "",
  48. // "data": "",
  49. // "code": "0"
  50. // },
  51. // "index": "0",
  52. // "height": "52",
  53. // "hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
  54. // },
  55. // "id": "",
  56. // "jsonrpc": "2.0"
  57. // }
  58. // ```
  59. //
  60. // Returns a transaction matching the given transaction hash.
  61. //
  62. // ### Query Parameters
  63. //
  64. // | Parameter | Type | Default | Required | Description |
  65. // |-----------+--------+---------+----------+-----------------------------------------------------------|
  66. // | hash | []byte | nil | true | The transaction hash |
  67. // | prove | bool | false | false | Include a proof of the transaction inclusion in the block |
  68. //
  69. // ### Returns
  70. //
  71. // - `proof`: the `types.TxProof` object
  72. // - `tx`: `[]byte` - the transaction
  73. // - `tx_result`: the `abci.Result` object
  74. // - `index`: `int` - index of the transaction
  75. // - `height`: `int` - height of the block where this transaction was in
  76. // - `hash`: `[]byte` - hash of the transaction
  77. func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
  78. // if index is disabled, return error
  79. if _, ok := txIndexer.(*null.TxIndex); ok {
  80. return nil, fmt.Errorf("Transaction indexing is disabled")
  81. }
  82. r, err := txIndexer.Get(hash)
  83. if err != nil {
  84. return nil, err
  85. }
  86. if r == nil {
  87. return nil, fmt.Errorf("Tx (%X) not found", hash)
  88. }
  89. height := r.Height
  90. index := r.Index
  91. var proof types.TxProof
  92. if prove {
  93. block := blockStore.LoadBlock(height)
  94. proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
  95. }
  96. return &ctypes.ResultTx{
  97. Hash: hash,
  98. Height: height,
  99. Index: index,
  100. TxResult: r.Result,
  101. Tx: r.Tx,
  102. Proof: proof,
  103. }, nil
  104. }
  105. // TxSearch allows you to query for multiple transactions results. It returns a
  106. // list of transactions (maximum ?per_page entries) and the total count.
  107. //
  108. // ```shell
  109. // curl "localhost:26657/tx_search?query=\"account.owner='Ivan'\"&prove=true"
  110. // ```
  111. //
  112. // ```go
  113. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  114. // err := client.Start()
  115. // if err != nil {
  116. // // handle error
  117. // }
  118. // defer client.Stop()
  119. // q, err := tmquery.New("account.owner='Ivan'")
  120. // tx, err := client.TxSearch(q, true)
  121. // ```
  122. //
  123. // > The above command returns JSON structured like this:
  124. //
  125. // ```json
  126. // {
  127. // "jsonrpc": "2.0",
  128. // "id": "",
  129. // "result": {
  130. // "txs": [
  131. // {
  132. // "proof": {
  133. // "Proof": {
  134. // "aunts": [
  135. // "J3LHbizt806uKnABNLwG4l7gXCA=",
  136. // "iblMO/M1TnNtlAefJyNCeVhjAb0=",
  137. // "iVk3ryurVaEEhdeS0ohAJZ3wtB8=",
  138. // "5hqMkTeGqpct51ohX0lZLIdsn7Q=",
  139. // "afhsNxFnLlZgFDoyPpdQSe0bR8g="
  140. // ]
  141. // },
  142. // "Data": "mvZHHa7HhZ4aRT0xMDA=",
  143. // "RootHash": "F6541223AA46E428CB1070E9840D2C3DF3B6D776",
  144. // "Total": "32",
  145. // "Index": "31"
  146. // },
  147. // "tx": "mvZHHa7HhZ4aRT0xMDA=",
  148. // "tx_result": {},
  149. // "index": "31",
  150. // "height": "12",
  151. // "hash": "2B8EC32BA2579B3B8606E42C06DE2F7AFA2556EF"
  152. // }
  153. // ],
  154. // "total_count": "1"
  155. // }
  156. // }
  157. // ```
  158. //
  159. // ### Query Parameters
  160. //
  161. // | Parameter | Type | Default | Required | Description |
  162. // |-----------+--------+---------+----------+-----------------------------------------------------------|
  163. // | query | string | "" | true | Query |
  164. // | prove | bool | false | false | Include proofs of the transactions inclusion in the block |
  165. // | page | int | 1 | false | Page number (1-based) |
  166. // | per_page | int | 30 | false | Number of entries per page (max: 100) |
  167. //
  168. // ### Returns
  169. //
  170. // - `proof`: the `types.TxProof` object
  171. // - `tx`: `[]byte` - the transaction
  172. // - `tx_result`: the `abci.Result` object
  173. // - `index`: `int` - index of the transaction
  174. // - `height`: `int` - height of the block where this transaction was in
  175. // - `hash`: `[]byte` - hash of the transaction
  176. func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) {
  177. // if index is disabled, return error
  178. if _, ok := txIndexer.(*null.TxIndex); ok {
  179. return nil, fmt.Errorf("Transaction indexing is disabled")
  180. }
  181. q, err := tmquery.New(query)
  182. if err != nil {
  183. return nil, err
  184. }
  185. results, err := txIndexer.Search(q)
  186. if err != nil {
  187. return nil, err
  188. }
  189. totalCount := len(results)
  190. perPage = validatePerPage(perPage)
  191. page, err = validatePage(page, perPage, totalCount)
  192. if err != nil {
  193. return nil, err
  194. }
  195. skipCount := validateSkipCount(page, perPage)
  196. apiResults := make([]*ctypes.ResultTx, cmn.MinInt(perPage, totalCount-skipCount))
  197. var proof types.TxProof
  198. // if there's no tx in the results array, we don't need to loop through the apiResults array
  199. for i := 0; i < len(apiResults); i++ {
  200. r := results[skipCount+i]
  201. height := r.Height
  202. index := r.Index
  203. if prove {
  204. block := blockStore.LoadBlock(height)
  205. proof = block.Data.Txs.Proof(int(index)) // XXX: overflow on 32-bit machines
  206. }
  207. apiResults[i] = &ctypes.ResultTx{
  208. Hash: r.Tx.Hash(),
  209. Height: height,
  210. Index: index,
  211. TxResult: r.Result,
  212. Tx: r.Tx,
  213. Proof: proof,
  214. }
  215. }
  216. return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil
  217. }