github.com/evdatsion/aphelion-dpos-bft@v0.32.1/rpc/core/status.go (about)

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