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.

263 lines
7.2 KiB

  1. package core
  2. import (
  3. cm "github.com/tendermint/tendermint/consensus"
  4. "github.com/tendermint/tendermint/p2p"
  5. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  6. sm "github.com/tendermint/tendermint/state"
  7. "github.com/tendermint/tendermint/types"
  8. )
  9. // Get the validator set at the given block height.
  10. // If no height is provided, it will fetch the current validator set.
  11. //
  12. // ```shell
  13. // curl 'localhost:26657/validators'
  14. // ```
  15. //
  16. // ```go
  17. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  18. // state, err := client.Validators()
  19. // ```
  20. //
  21. // The above command returns JSON structured like this:
  22. //
  23. // ```json
  24. // {
  25. // "error": "",
  26. // "result": {
  27. // "validators": [
  28. // {
  29. // "accum": 0,
  30. // "voting_power": 10,
  31. // "pub_key": {
  32. // "data": "68DFDA7E50F82946E7E8546BED37944A422CD1B831E70DF66BA3B8430593944D",
  33. // "type": "ed25519"
  34. // },
  35. // "address": "E89A51D60F68385E09E716D353373B11F8FACD62"
  36. // }
  37. // ],
  38. // "block_height": 5241
  39. // },
  40. // "id": "",
  41. // "jsonrpc": "2.0"
  42. // }
  43. // ```
  44. func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) {
  45. // The latest validator that we know is the
  46. // NextValidator of the last block.
  47. height := consensusState.GetState().LastBlockHeight + 1
  48. height, err := getHeight(height, heightPtr)
  49. if err != nil {
  50. return nil, err
  51. }
  52. validators, err := sm.LoadValidators(stateDB, height)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return &ctypes.ResultValidators{height, validators.Validators}, nil
  57. }
  58. // DumpConsensusState dumps consensus state.
  59. // UNSTABLE
  60. //
  61. // ```shell
  62. // curl 'localhost:26657/dump_consensus_state'
  63. // ```
  64. //
  65. // ```go
  66. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  67. // state, err := client.DumpConsensusState()
  68. // ```
  69. //
  70. // The above command returns JSON structured like this:
  71. //
  72. // ```json
  73. // {
  74. // "jsonrpc": "2.0",
  75. // "id": "",
  76. // "result": {
  77. // "round_state": {
  78. // "height": 7185,
  79. // "round": 0,
  80. // "step": 1,
  81. // "start_time": "2018-05-12T13:57:28.440293621-07:00",
  82. // "commit_time": "2018-05-12T13:57:27.440293621-07:00",
  83. // "validators": {
  84. // "validators": [
  85. // {
  86. // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244",
  87. // "pub_key": {
  88. // "type": "tendermint/PubKeyEd25519",
  89. // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg="
  90. // },
  91. // "voting_power": 10,
  92. // "accum": 0
  93. // }
  94. // ],
  95. // "proposer": {
  96. // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244",
  97. // "pub_key": {
  98. // "type": "tendermint/PubKeyEd25519",
  99. // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg="
  100. // },
  101. // "voting_power": 10,
  102. // "accum": 0
  103. // }
  104. // },
  105. // "proposal": null,
  106. // "proposal_block": null,
  107. // "proposal_block_parts": null,
  108. // "locked_round": 0,
  109. // "locked_block": null,
  110. // "locked_block_parts": null,
  111. // "valid_round": 0,
  112. // "valid_block": null,
  113. // "valid_block_parts": null,
  114. // "votes": [
  115. // {
  116. // "round": 0,
  117. // "prevotes": "_",
  118. // "precommits": "_"
  119. // }
  120. // ],
  121. // "commit_round": -1,
  122. // "last_commit": {
  123. // "votes": [
  124. // "Vote{0:B5B3D40BE539 7184/00/2(Precommit) 14F946FA7EF0 /702B1B1A602A.../ @ 2018-05-12T20:57:27.342Z}"
  125. // ],
  126. // "votes_bit_array": "x",
  127. // "peer_maj_23s": {}
  128. // },
  129. // "last_validators": {
  130. // "validators": [
  131. // {
  132. // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244",
  133. // "pub_key": {
  134. // "type": "tendermint/PubKeyEd25519",
  135. // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg="
  136. // },
  137. // "voting_power": 10,
  138. // "accum": 0
  139. // }
  140. // ],
  141. // "proposer": {
  142. // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244",
  143. // "pub_key": {
  144. // "type": "tendermint/PubKeyEd25519",
  145. // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg="
  146. // },
  147. // "voting_power": 10,
  148. // "accum": 0
  149. // }
  150. // }
  151. // },
  152. // "peers": [
  153. // {
  154. // "node_address": "30ad1854af22506383c3f0e57fb3c7f90984c5e8@172.16.63.221:26656",
  155. // "peer_state": {
  156. // "round_state": {
  157. // "height": 7185,
  158. // "round": 0,
  159. // "step": 1,
  160. // "start_time": "2018-05-12T13:57:27.438039872-07:00",
  161. // "proposal": false,
  162. // "proposal_block_parts_header": {
  163. // "total": 0,
  164. // "hash": ""
  165. // },
  166. // "proposal_block_parts": null,
  167. // "proposal_pol_round": -1,
  168. // "proposal_pol": "_",
  169. // "prevotes": "_",
  170. // "precommits": "_",
  171. // "last_commit_round": 0,
  172. // "last_commit": "x",
  173. // "catchup_commit_round": -1,
  174. // "catchup_commit": "_"
  175. // },
  176. // "stats": {
  177. // "last_vote_height": 7184,
  178. // "votes": 255,
  179. // "last_block_part_height": 7184,
  180. // "block_parts": 255
  181. // }
  182. // }
  183. // }
  184. // ]
  185. // }
  186. // }
  187. // ```
  188. func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
  189. // Get Peer consensus states.
  190. peers := p2pSwitch.Peers().List()
  191. peerStates := make([]ctypes.PeerStateInfo, len(peers))
  192. for i, peer := range peers {
  193. peerState := peer.Get(types.PeerStateKey).(*cm.PeerState)
  194. peerStateJSON, err := peerState.ToJSON()
  195. if err != nil {
  196. return nil, err
  197. }
  198. peerStates[i] = ctypes.PeerStateInfo{
  199. // Peer basic info.
  200. NodeAddress: p2p.IDAddressString(peer.ID(), peer.NodeInfo().ListenAddr),
  201. // Peer consensus state.
  202. PeerState: peerStateJSON,
  203. }
  204. }
  205. // Get self round state.
  206. roundState, err := consensusState.GetRoundStateJSON()
  207. if err != nil {
  208. return nil, err
  209. }
  210. return &ctypes.ResultDumpConsensusState{roundState, peerStates}, nil
  211. }
  212. // ConsensusState returns a concise summary of the consensus state.
  213. // UNSTABLE
  214. //
  215. // ```shell
  216. // curl 'localhost:26657/consensus_state'
  217. // ```
  218. //
  219. // ```go
  220. // client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
  221. // state, err := client.ConsensusState()
  222. // ```
  223. //
  224. // The above command returns JSON structured like this:
  225. //
  226. // ```json
  227. //{
  228. // "jsonrpc": "2.0",
  229. // "id": "",
  230. // "result": {
  231. // "round_state": {
  232. // "height/round/step": "9336/0/1",
  233. // "start_time": "2018-05-14T10:25:45.72595357-04:00",
  234. // "proposal_block_hash": "",
  235. // "locked_block_hash": "",
  236. // "valid_block_hash": "",
  237. // "height_vote_set": [
  238. // {
  239. // "round": 0,
  240. // "prevotes": [
  241. // "nil-Vote"
  242. // ],
  243. // "prevotes_bit_array": "BA{1:_} 0/10 = 0.00",
  244. // "precommits": [
  245. // "nil-Vote"
  246. // ],
  247. // "precommits_bit_array": "BA{1:_} 0/10 = 0.00"
  248. // }
  249. // ]
  250. // }
  251. // }
  252. //}
  253. //```
  254. func ConsensusState() (*ctypes.ResultConsensusState, error) {
  255. // Get self round state.
  256. bz, err := consensusState.GetRoundStateSimpleJSON()
  257. return &ctypes.ResultConsensusState{bz}, err
  258. }