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.

132 lines
3.3 KiB

  1. package core
  2. import (
  3. "bytes"
  4. "time"
  5. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  6. sm "github.com/tendermint/tendermint/state"
  7. "github.com/tendermint/tendermint/types"
  8. cmn "github.com/tendermint/tmlibs/common"
  9. )
  10. // Get Tendermint status including node info, pubkey, latest block
  11. // hash, app hash, block height and time.
  12. //
  13. // ```shell
  14. // curl 'localhost:46657/status'
  15. // ```
  16. //
  17. // ```go
  18. // client := client.NewHTTP("tcp://0.0.0.0:46657", "/websocket")
  19. // result, err := client.Status()
  20. // ```
  21. //
  22. // > The above command returns JSON structured like this:
  23. //
  24. // ```json
  25. // {
  26. // "result": {
  27. // "sync_info": {
  28. // "syncing": false,
  29. // "latest_block_time": "2017-12-07T18:19:47.617Z",
  30. // "latest_block_height": 6,
  31. // "latest_app_hash": "",
  32. // "latest_block_hash": "A63D0C3307DEDCCFCC82ED411AE9108B70B29E02",
  33. // }
  34. // "validator_info": {
  35. // "pub_key": {
  36. // "data": "8C9A68070CBE33F9C445862BA1E9D96A75CEB68C0CF6ADD3652D07DCAC5D0380",
  37. // "type": "ed25519"
  38. // },
  39. // "voting_power": 10
  40. // }
  41. // "node_info": {
  42. // "other": [
  43. // "wire_version=0.7.2",
  44. // "p2p_version=0.5.0",
  45. // "consensus_version=v1/0.2.2",
  46. // "rpc_version=0.7.0/3",
  47. // "tx_index=on",
  48. // "rpc_addr=tcp://0.0.0.0:46657"
  49. // ],
  50. // "version": "0.13.0-14ccc8b",
  51. // "listen_addr": "10.0.2.15:46656",
  52. // "remote_addr": "",
  53. // "network": "test-chain-qhVCa2",
  54. // "moniker": "vagrant-ubuntu-trusty-64",
  55. // "pub_key": "844981FE99ABB19F7816F2D5E94E8A74276AB1153760A7799E925C75401856C6",
  56. // }
  57. // },
  58. // "id": "",
  59. // "jsonrpc": "2.0"
  60. // }
  61. // ```
  62. func Status() (*ctypes.ResultStatus, error) {
  63. latestHeight := blockStore.Height()
  64. var (
  65. latestBlockMeta *types.BlockMeta
  66. latestBlockHash cmn.HexBytes
  67. latestAppHash cmn.HexBytes
  68. latestBlockTimeNano int64
  69. )
  70. if latestHeight != 0 {
  71. latestBlockMeta = blockStore.LoadBlockMeta(latestHeight)
  72. latestBlockHash = latestBlockMeta.BlockID.Hash
  73. latestAppHash = latestBlockMeta.Header.AppHash
  74. latestBlockTimeNano = latestBlockMeta.Header.Time.UnixNano()
  75. }
  76. latestBlockTime := time.Unix(0, latestBlockTimeNano)
  77. var votingPower int64
  78. if val := validatorAtHeight(latestHeight); val != nil {
  79. votingPower = val.VotingPower
  80. }
  81. result := &ctypes.ResultStatus{
  82. NodeInfo: p2pSwitch.NodeInfo(),
  83. SyncInfo: ctypes.SyncInfo{
  84. LatestBlockHash: latestBlockHash,
  85. LatestAppHash: latestAppHash,
  86. LatestBlockHeight: latestHeight,
  87. LatestBlockTime: latestBlockTime,
  88. Syncing: consensusReactor.FastSync(),
  89. },
  90. ValidatorInfo: ctypes.ValidatorInfo{
  91. Address: pubKey.Address(),
  92. PubKey: pubKey,
  93. VotingPower: votingPower,
  94. },
  95. }
  96. return result, nil
  97. }
  98. func validatorAtHeight(h int64) *types.Validator {
  99. lastBlockHeight, vals := consensusState.GetValidators()
  100. privValAddress := pubKey.Address()
  101. // if we're still at height h, search in the current validator set
  102. if lastBlockHeight == h {
  103. for _, val := range vals {
  104. if bytes.Equal(val.Address, privValAddress) {
  105. return val
  106. }
  107. }
  108. }
  109. // if we've moved to the next height, retrieve the validator set from DB
  110. if lastBlockHeight > h {
  111. vals, err := sm.LoadValidators(stateDB, h)
  112. if err != nil {
  113. // should not happen
  114. return nil
  115. }
  116. _, val := vals.GetByAddress(privValAddress)
  117. return val
  118. }
  119. return nil
  120. }