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.

143 lines
3.6 KiB

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