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.

144 lines
3.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>
5 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>
5 years ago
  1. package core
  2. import (
  3. "bytes"
  4. "time"
  5. cmn "github.com/tendermint/tendermint/libs/common"
  6. "github.com/tendermint/tendermint/p2p"
  7. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  8. rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
  9. sm "github.com/tendermint/tendermint/state"
  10. "github.com/tendermint/tendermint/types"
  11. )
  12. // Get Tendermint status including node info, pubkey, latest block
  13. // hash, app hash, block height and time.
  14. //
  15. // ```shell
  16. // curl 'localhost:26657/status'
  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. // result, err := client.Status()
  27. // ```
  28. //
  29. // > The above command returns JSON structured like this:
  30. //
  31. // ```json
  32. // {
  33. // "jsonrpc": "2.0",
  34. // "id": "",
  35. // "result": {
  36. // "node_info": {
  37. // "protocol_version": {
  38. // "p2p": "4",
  39. // "block": "7",
  40. // "app": "0"
  41. // },
  42. // "id": "53729852020041b956e86685e24394e0bee4373f",
  43. // "listen_addr": "10.0.2.15:26656",
  44. // "network": "test-chain-Y1OHx6",
  45. // "version": "0.24.0-2ce1abc2",
  46. // "channels": "4020212223303800",
  47. // "moniker": "ubuntu-xenial",
  48. // "other": {
  49. // "tx_index": "on",
  50. // "rpc_addr": "tcp://0.0.0.0:26657"
  51. // }
  52. // },
  53. // "sync_info": {
  54. // "latest_block_hash": "F51538DA498299F4C57AC8162AAFA0254CE08286",
  55. // "latest_app_hash": "0000000000000000",
  56. // "latest_block_height": "18",
  57. // "latest_block_time": "2018-09-17T11:42:19.149920551Z",
  58. // "catching_up": false
  59. // },
  60. // "validator_info": {
  61. // "address": "D9F56456D7C5793815D0E9AF07C3A355D0FC64FD",
  62. // "pub_key": {
  63. // "type": "tendermint/PubKeyEd25519",
  64. // "value": "wVxKNtEsJmR4vvh651LrVoRguPs+6yJJ9Bz174gw9DM="
  65. // },
  66. // "voting_power": "10"
  67. // }
  68. // }
  69. // }
  70. // ```
  71. func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
  72. var latestHeight int64
  73. if consensusReactor.FastSync() {
  74. latestHeight = blockStore.Height()
  75. } else {
  76. latestHeight = consensusState.GetLastHeight()
  77. }
  78. var (
  79. latestBlockMeta *types.BlockMeta
  80. latestBlockHash cmn.HexBytes
  81. latestAppHash cmn.HexBytes
  82. latestBlockTimeNano int64
  83. )
  84. if latestHeight != 0 {
  85. latestBlockMeta = blockStore.LoadBlockMeta(latestHeight)
  86. latestBlockHash = latestBlockMeta.BlockID.Hash
  87. latestAppHash = latestBlockMeta.Header.AppHash
  88. latestBlockTimeNano = latestBlockMeta.Header.Time.UnixNano()
  89. }
  90. latestBlockTime := time.Unix(0, latestBlockTimeNano)
  91. var votingPower int64
  92. if val := validatorAtHeight(latestHeight); val != nil {
  93. votingPower = val.VotingPower
  94. }
  95. result := &ctypes.ResultStatus{
  96. NodeInfo: p2pTransport.NodeInfo().(p2p.DefaultNodeInfo),
  97. SyncInfo: ctypes.SyncInfo{
  98. LatestBlockHash: latestBlockHash,
  99. LatestAppHash: latestAppHash,
  100. LatestBlockHeight: latestHeight,
  101. LatestBlockTime: latestBlockTime,
  102. CatchingUp: consensusReactor.FastSync(),
  103. },
  104. ValidatorInfo: ctypes.ValidatorInfo{
  105. Address: pubKey.Address(),
  106. PubKey: pubKey,
  107. VotingPower: votingPower,
  108. },
  109. }
  110. return result, nil
  111. }
  112. func validatorAtHeight(h int64) *types.Validator {
  113. privValAddress := pubKey.Address()
  114. // If we're still at height h, search in the current validator set.
  115. lastBlockHeight, vals := consensusState.GetValidators()
  116. if lastBlockHeight == h {
  117. for _, val := range vals {
  118. if bytes.Equal(val.Address, privValAddress) {
  119. return val
  120. }
  121. }
  122. }
  123. // If we've moved to the next height, retrieve the validator set from DB.
  124. if lastBlockHeight > h {
  125. vals, err := sm.LoadValidators(stateDB, h)
  126. if err != nil {
  127. return nil // should not happen
  128. }
  129. _, val := vals.GetByAddress(privValAddress)
  130. return val
  131. }
  132. return nil
  133. }