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.

422 lines
11 KiB

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>
5 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>
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
8 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
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 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>
5 years ago
  1. package core
  2. import (
  3. "fmt"
  4. cmn "github.com/tendermint/tendermint/libs/common"
  5. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  6. rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
  7. sm "github.com/tendermint/tendermint/state"
  8. "github.com/tendermint/tendermint/types"
  9. )
  10. // Get block headers for minHeight <= height <= maxHeight.
  11. // Block headers are returned in descending order (highest first).
  12. //
  13. // ```shell
  14. // curl 'localhost:26657/blockchain?minHeight=10&maxHeight=10'
  15. // ```
  16. //
  17. // ```go
  18. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  19. // err := client.Start()
  20. // if err != nil {
  21. // // handle error
  22. // }
  23. // defer client.Stop()
  24. // info, err := client.BlockchainInfo(10, 10)
  25. // ```
  26. //
  27. // > The above command returns JSON structured like this:
  28. //
  29. // ```json
  30. // {
  31. // "error": "",
  32. // "result": {
  33. // "block_metas": [
  34. // {
  35. // "header": {
  36. // "app_hash": "",
  37. // "chain_id": "test-chain-6UTNIN",
  38. // "height": "10",
  39. // "time": "2017-05-29T15:05:53.877Z",
  40. // "num_txs": "0",
  41. // "last_block_id": {
  42. // "parts": {
  43. // "hash": "3C78F00658E06744A88F24FF97A0A5011139F34A",
  44. // "total": "1"
  45. // },
  46. // "hash": "F70588DAB36BDA5A953D548A16F7D48C6C2DFD78"
  47. // },
  48. // "last_commit_hash": "F31CC4282E50B3F2A58D763D233D76F26D26CABE",
  49. // "data_hash": "",
  50. // "validators_hash": "9365FC80F234C967BD233F5A3E2AB2F1E4B0E5AA"
  51. // },
  52. // "block_id": {
  53. // "parts": {
  54. // "hash": "277A4DBEF91483A18B85F2F5677ABF9694DFA40F",
  55. // "total": "1"
  56. // },
  57. // "hash": "96B1D2F2D201BA4BC383EB8224139DB1294944E5"
  58. // }
  59. // }
  60. // ],
  61. // "last_height": "5493"
  62. // },
  63. // "id": "",
  64. // "jsonrpc": "2.0"
  65. // }
  66. // ```
  67. //
  68. // <aside class="notice">Returns at most 20 items.</aside>
  69. func BlockchainInfo(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
  70. // maximum 20 block metas
  71. const limit int64 = 20
  72. var err error
  73. minHeight, maxHeight, err = filterMinMax(blockStore.Height(), minHeight, maxHeight, limit)
  74. if err != nil {
  75. return nil, err
  76. }
  77. logger.Debug("BlockchainInfoHandler", "maxHeight", maxHeight, "minHeight", minHeight)
  78. blockMetas := []*types.BlockMeta{}
  79. for height := maxHeight; height >= minHeight; height-- {
  80. blockMeta := blockStore.LoadBlockMeta(height)
  81. blockMetas = append(blockMetas, blockMeta)
  82. }
  83. return &ctypes.ResultBlockchainInfo{
  84. LastHeight: blockStore.Height(),
  85. BlockMetas: blockMetas}, nil
  86. }
  87. // error if either min or max are negative or min < max
  88. // if 0, use 1 for min, latest block height for max
  89. // enforce limit.
  90. // error if min > max
  91. func filterMinMax(height, min, max, limit int64) (int64, int64, error) {
  92. // filter negatives
  93. if min < 0 || max < 0 {
  94. return min, max, fmt.Errorf("heights must be non-negative")
  95. }
  96. // adjust for default values
  97. if min == 0 {
  98. min = 1
  99. }
  100. if max == 0 {
  101. max = height
  102. }
  103. // limit max to the height
  104. max = cmn.MinInt64(height, max)
  105. // limit min to within `limit` of max
  106. // so the total number of blocks returned will be `limit`
  107. min = cmn.MaxInt64(min, max-limit+1)
  108. if min > max {
  109. return min, max, fmt.Errorf("min height %d can't be greater than max height %d", min, max)
  110. }
  111. return min, max, nil
  112. }
  113. // Get block at a given height.
  114. // If no height is provided, it will fetch the latest block.
  115. //
  116. // ```shell
  117. // curl 'localhost:26657/block?height=10'
  118. // ```
  119. //
  120. // ```go
  121. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  122. // err := client.Start()
  123. // if err != nil {
  124. // // handle error
  125. // }
  126. // defer client.Stop()
  127. // info, err := client.Block(10)
  128. // ```
  129. //
  130. // > The above command returns JSON structured like this:
  131. //
  132. // ```json
  133. // {
  134. // "error": "",
  135. // "result": {
  136. // "block": {
  137. // "last_commit": {
  138. // "precommits": [
  139. // {
  140. // "signature": {
  141. // "data": "12C0D8893B8A38224488DC1DE6270DF76BB1A5E9DB" +
  142. // "1C68577706A6A97C6EC34FFD12339183D5CA8BC2F4" +
  143. // "6148773823DE905B7F6F5862FD564038BB7AE03BF50D",
  144. // "type": "ed25519"
  145. // },
  146. // "block_id": {
  147. // "parts": {
  148. // "hash": "3C78F00658E06744A88F24FF97A0A5011139F34A",
  149. // "total": "1"
  150. // },
  151. // "hash": "F70588DAB36BDA5A953D548A16F7D48C6C2DFD78"
  152. // },
  153. // "type": "2",
  154. // "round": "0",
  155. // "height": "9",
  156. // "validator_index": "0",
  157. // "validator_address": "E89A51D60F68385E09E716D353373B11F8FACD62"
  158. // }
  159. // ],
  160. // "blockID": {
  161. // "parts": {
  162. // "hash": "3C78F00658E06744A88F24FF97A0A5011139F34A",
  163. // "total": "1"
  164. // },
  165. // "hash": "F70588DAB36BDA5A953D548A16F7D48C6C2DFD78"
  166. // }
  167. // },
  168. // "data": {
  169. // "txs": []
  170. // },
  171. // "header": {
  172. // "app_hash": "",
  173. // "chain_id": "test-chain-6UTNIN",
  174. // "height": "10",
  175. // "time": "2017-05-29T15:05:53.877Z",
  176. // "num_txs": "0",
  177. // "last_block_id": {
  178. // "parts": {
  179. // "hash": "3C78F00658E06744A88F24FF97A0A5011139F34A",
  180. // "total": "1"
  181. // },
  182. // "hash": "F70588DAB36BDA5A953D548A16F7D48C6C2DFD78"
  183. // },
  184. // "last_commit_hash": "F31CC4282E50B3F2A58D763D233D76F26D26CABE",
  185. // "data_hash": "",
  186. // "validators_hash": "9365FC80F234C967BD233F5A3E2AB2F1E4B0E5AA"
  187. // }
  188. // },
  189. // "block_meta": {
  190. // "header": {
  191. // "app_hash": "",
  192. // "chain_id": "test-chain-6UTNIN",
  193. // "height": "10",
  194. // "time": "2017-05-29T15:05:53.877Z",
  195. // "num_txs": "0",
  196. // "last_block_id": {
  197. // "parts": {
  198. // "hash": "3C78F00658E06744A88F24FF97A0A5011139F34A",
  199. // "total": "1"
  200. // },
  201. // "hash": "F70588DAB36BDA5A953D548A16F7D48C6C2DFD78"
  202. // },
  203. // "last_commit_hash": "F31CC4282E50B3F2A58D763D233D76F26D26CABE",
  204. // "data_hash": "",
  205. // "validators_hash": "9365FC80F234C967BD233F5A3E2AB2F1E4B0E5AA"
  206. // },
  207. // "block_id": {
  208. // "parts": {
  209. // "hash": "277A4DBEF91483A18B85F2F5677ABF9694DFA40F",
  210. // "total": "1"
  211. // },
  212. // "hash": "96B1D2F2D201BA4BC383EB8224139DB1294944E5"
  213. // }
  214. // }
  215. // },
  216. // "id": "",
  217. // "jsonrpc": "2.0"
  218. // }
  219. // ```
  220. func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) {
  221. storeHeight := blockStore.Height()
  222. height, err := getHeight(storeHeight, heightPtr)
  223. if err != nil {
  224. return nil, err
  225. }
  226. blockMeta := blockStore.LoadBlockMeta(height)
  227. block := blockStore.LoadBlock(height)
  228. return &ctypes.ResultBlock{BlockMeta: blockMeta, Block: block}, nil
  229. }
  230. // Get block commit at a given height.
  231. // If no height is provided, it will fetch the commit for the latest block.
  232. //
  233. // ```shell
  234. // curl 'localhost:26657/commit?height=11'
  235. // ```
  236. //
  237. // ```go
  238. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  239. // err := client.Start()
  240. // if err != nil {
  241. // // handle error
  242. // }
  243. // defer client.Stop()
  244. // info, err := client.Commit(11)
  245. // ```
  246. //
  247. // > The above command returns JSON structured like this:
  248. //
  249. // ```json
  250. // {
  251. // "error": "",
  252. // "result": {
  253. // "canonical": true,
  254. // "commit": {
  255. // "precommits": [
  256. // {
  257. // "signature": {
  258. // "data": "00970429FEC652E9E21D106A90AE8C5413759A74887" +
  259. // "75CEF4A3F44DC46C7F9D941070E4FBE9ED54DF247FA" +
  260. // "3983359A0C3A238D61DE55C75C9116D72ABC9CF50F",
  261. // "type": "ed25519"
  262. // },
  263. // "block_id": {
  264. // "parts": {
  265. // "hash": "9E37CBF266BC044A779E09D81C456E653B89E006",
  266. // "total": "1"
  267. // },
  268. // "hash": "CC6E861E31CA4334E9888381B4A9137D1458AB6A"
  269. // },
  270. // "type": "2",
  271. // "round": "0",
  272. // "height": "11",
  273. // "validator_index": "0",
  274. // "validator_address": "E89A51D60F68385E09E716D353373B11F8FACD62"
  275. // }
  276. // ],
  277. // "blockID": {
  278. // "parts": {
  279. // "hash": "9E37CBF266BC044A779E09D81C456E653B89E006",
  280. // "total": "1"
  281. // },
  282. // "hash": "CC6E861E31CA4334E9888381B4A9137D1458AB6A"
  283. // }
  284. // },
  285. // "header": {
  286. // "app_hash": "",
  287. // "chain_id": "test-chain-6UTNIN",
  288. // "height": "11",
  289. // "time": "2017-05-29T15:05:54.893Z",
  290. // "num_txs": "0",
  291. // "last_block_id": {
  292. // "parts": {
  293. // "hash": "277A4DBEF91483A18B85F2F5677ABF9694DFA40F",
  294. // "total": "1"
  295. // },
  296. // "hash": "96B1D2F2D201BA4BC383EB8224139DB1294944E5"
  297. // },
  298. // "last_commit_hash": "3CE0C9727CE524BA9CB7C91E28F08E2B94001087",
  299. // "data_hash": "",
  300. // "validators_hash": "9365FC80F234C967BD233F5A3E2AB2F1E4B0E5AA"
  301. // }
  302. // },
  303. // "id": "",
  304. // "jsonrpc": "2.0"
  305. // }
  306. // ```
  307. func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, error) {
  308. storeHeight := blockStore.Height()
  309. height, err := getHeight(storeHeight, heightPtr)
  310. if err != nil {
  311. return nil, err
  312. }
  313. header := blockStore.LoadBlockMeta(height).Header
  314. // If the next block has not been committed yet,
  315. // use a non-canonical commit
  316. if height == storeHeight {
  317. commit := blockStore.LoadSeenCommit(height)
  318. return ctypes.NewResultCommit(&header, commit, false), nil
  319. }
  320. // Return the canonical commit (comes from the block at height+1)
  321. commit := blockStore.LoadBlockCommit(height)
  322. return ctypes.NewResultCommit(&header, commit, true), nil
  323. }
  324. // BlockResults gets ABCIResults at a given height.
  325. // If no height is provided, it will fetch results for the latest block.
  326. //
  327. // Results are for the height of the block containing the txs.
  328. // Thus response.results.deliver_tx[5] is the results of executing
  329. // getBlock(h).Txs[5]
  330. //
  331. // ```shell
  332. // curl 'localhost:26657/block_results?height=10'
  333. // ```
  334. //
  335. // ```go
  336. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  337. // err := client.Start()
  338. // if err != nil {
  339. // // handle error
  340. // }
  341. // defer client.Stop()
  342. // info, err := client.BlockResults(10)
  343. // ```
  344. //
  345. //
  346. // > The above command returns JSON structured like this:
  347. //
  348. // ```json
  349. // {
  350. // "jsonrpc": "2.0",
  351. // "id": "",
  352. // "result": {
  353. // "height": "39",
  354. // "results": {
  355. // "deliver_tx": [
  356. // {
  357. // "tags": [
  358. // {
  359. // "key": "YXBwLmNyZWF0b3I=",
  360. // "value": "Q29zbW9zaGkgTmV0b3dva28="
  361. // }
  362. // ]
  363. // }
  364. // ],
  365. // "end_block": {
  366. // "validator_updates": null
  367. // },
  368. // "begin_block": {}
  369. // }
  370. // }
  371. // }
  372. // ```
  373. func BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockResults, error) {
  374. storeHeight := blockStore.Height()
  375. height, err := getHeight(storeHeight, heightPtr)
  376. if err != nil {
  377. return nil, err
  378. }
  379. results, err := sm.LoadABCIResponses(stateDB, height)
  380. if err != nil {
  381. return nil, err
  382. }
  383. res := &ctypes.ResultBlockResults{
  384. Height: height,
  385. Results: results,
  386. }
  387. return res, nil
  388. }
  389. func getHeight(currentHeight int64, heightPtr *int64) (int64, error) {
  390. if heightPtr != nil {
  391. height := *heightPtr
  392. if height <= 0 {
  393. return 0, fmt.Errorf("Height must be greater than 0")
  394. }
  395. if height > currentHeight {
  396. return 0, fmt.Errorf("Height must be less than or equal to the current blockchain height")
  397. }
  398. return height, nil
  399. }
  400. return currentHeight, nil
  401. }