package core
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/tendermint/tendermint/p2p"
|
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
|
rpctypes "github.com/tendermint/tendermint/rpc/lib/types"
|
|
)
|
|
|
|
// Get network info.
|
|
//
|
|
// ```shell
|
|
// curl 'localhost:26657/net_info'
|
|
// ```
|
|
//
|
|
// ```go
|
|
// client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
|
|
// err := client.Start()
|
|
// if err != nil {
|
|
// // handle error
|
|
// }
|
|
// defer client.Stop()
|
|
// info, err := client.NetInfo()
|
|
// ```
|
|
//
|
|
// > The above command returns JSON structured like this:
|
|
//
|
|
// ```json
|
|
// {
|
|
// "jsonrpc": "2.0",
|
|
// "id": "",
|
|
// "result": {
|
|
// "listening": true,
|
|
// "listeners": [
|
|
// "Listener(@)"
|
|
// ],
|
|
// "n_peers": "3",
|
|
// "peers": [
|
|
// {
|
|
// "node_info": {
|
|
// "protocol_version": {
|
|
// "p2p": "7",
|
|
// "block": "8",
|
|
// "app": "1"
|
|
// },
|
|
// "id": "93529da3435c090d02251a050342b6a488d4ab56",
|
|
// "listen_addr": "tcp://0.0.0.0:26656",
|
|
// "network": "chain-RFo6qC",
|
|
// "version": "0.30.0",
|
|
// "channels": "4020212223303800",
|
|
// "moniker": "fc89e4ed23f2",
|
|
// "other": {
|
|
// "tx_index": "on",
|
|
// "rpc_address": "tcp://0.0.0.0:26657"
|
|
// }
|
|
// },
|
|
// "is_outbound": true,
|
|
// "connection_status": {
|
|
// "Duration": "3475230558",
|
|
// "SendMonitor": {
|
|
// "Active": true,
|
|
// "Start": "2019-02-14T12:40:47.52Z",
|
|
// "Duration": "3480000000",
|
|
// "Idle": "240000000",
|
|
// "Bytes": "4512",
|
|
// "Samples": "9",
|
|
// "InstRate": "1338",
|
|
// "CurRate": "2046",
|
|
// "AvgRate": "1297",
|
|
// "PeakRate": "6570",
|
|
// "BytesRem": "0",
|
|
// "TimeRem": "0",
|
|
// "Progress": 0
|
|
// },
|
|
// "RecvMonitor": {
|
|
// "Active": true,
|
|
// "Start": "2019-02-14T12:40:47.52Z",
|
|
// "Duration": "3480000000",
|
|
// "Idle": "280000000",
|
|
// "Bytes": "4489",
|
|
// "Samples": "10",
|
|
// "InstRate": "1821",
|
|
// "CurRate": "1663",
|
|
// "AvgRate": "1290",
|
|
// "PeakRate": "5512",
|
|
// "BytesRem": "0",
|
|
// "TimeRem": "0",
|
|
// "Progress": 0
|
|
// },
|
|
// "Channels": [
|
|
// {
|
|
// "ID": 48,
|
|
// "SendQueueCapacity": "1",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "5",
|
|
// "RecentlySent": "0"
|
|
// },
|
|
// {
|
|
// "ID": 64,
|
|
// "SendQueueCapacity": "1000",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "10",
|
|
// "RecentlySent": "14"
|
|
// },
|
|
// {
|
|
// "ID": 32,
|
|
// "SendQueueCapacity": "100",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "5",
|
|
// "RecentlySent": "619"
|
|
// },
|
|
// {
|
|
// "ID": 33,
|
|
// "SendQueueCapacity": "100",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "10",
|
|
// "RecentlySent": "1363"
|
|
// },
|
|
// {
|
|
// "ID": 34,
|
|
// "SendQueueCapacity": "100",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "5",
|
|
// "RecentlySent": "2145"
|
|
// },
|
|
// {
|
|
// "ID": 35,
|
|
// "SendQueueCapacity": "2",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "1",
|
|
// "RecentlySent": "0"
|
|
// },
|
|
// {
|
|
// "ID": 56,
|
|
// "SendQueueCapacity": "1",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "5",
|
|
// "RecentlySent": "0"
|
|
// },
|
|
// {
|
|
// "ID": 0,
|
|
// "SendQueueCapacity": "10",
|
|
// "SendQueueSize": "0",
|
|
// "Priority": "1",
|
|
// "RecentlySent": "10"
|
|
// }
|
|
// ]
|
|
// },
|
|
// "remote_ip": "192.167.10.3"
|
|
// },
|
|
// ...
|
|
// }
|
|
// ```
|
|
func NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, error) {
|
|
out, in, _ := p2pPeers.NumPeers()
|
|
peers := make([]ctypes.Peer, 0, out+in)
|
|
for _, peer := range p2pPeers.Peers().List() {
|
|
nodeInfo, ok := peer.NodeInfo().(p2p.DefaultNodeInfo)
|
|
if !ok {
|
|
return nil, fmt.Errorf("peer.NodeInfo() is not DefaultNodeInfo")
|
|
}
|
|
peers = append(peers, ctypes.Peer{
|
|
NodeInfo: nodeInfo,
|
|
IsOutbound: peer.IsOutbound(),
|
|
ConnectionStatus: peer.Status(),
|
|
RemoteIP: peer.RemoteIP().String(),
|
|
})
|
|
}
|
|
// TODO: Should we include PersistentPeers and Seeds in here?
|
|
// PRO: useful info
|
|
// CON: privacy
|
|
return &ctypes.ResultNetInfo{
|
|
Listening: p2pTransport.IsListening(),
|
|
Listeners: p2pTransport.Listeners(),
|
|
NPeers: len(peers),
|
|
Peers: peers,
|
|
}, nil
|
|
}
|
|
|
|
func UnsafeDialSeeds(ctx *rpctypes.Context, seeds []string) (*ctypes.ResultDialSeeds, error) {
|
|
if len(seeds) == 0 {
|
|
return &ctypes.ResultDialSeeds{}, errors.New("No seeds provided")
|
|
}
|
|
// starts go routines to dial each peer after random delays
|
|
logger.Info("DialSeeds", "addrBook", addrBook, "seeds", seeds)
|
|
err := p2pPeers.DialPeersAsync(addrBook, seeds, false)
|
|
if err != nil {
|
|
return &ctypes.ResultDialSeeds{}, err
|
|
}
|
|
return &ctypes.ResultDialSeeds{Log: "Dialing seeds in progress. See /net_info for details"}, nil
|
|
}
|
|
|
|
func UnsafeDialPeers(ctx *rpctypes.Context, peers []string, persistent bool) (*ctypes.ResultDialPeers, error) {
|
|
if len(peers) == 0 {
|
|
return &ctypes.ResultDialPeers{}, errors.New("No peers provided")
|
|
}
|
|
// starts go routines to dial each peer after random delays
|
|
logger.Info("DialPeers", "addrBook", addrBook, "peers", peers, "persistent", persistent)
|
|
err := p2pPeers.DialPeersAsync(addrBook, peers, persistent)
|
|
if err != nil {
|
|
return &ctypes.ResultDialPeers{}, err
|
|
}
|
|
return &ctypes.ResultDialPeers{Log: "Dialing peers in progress. See /net_info for details"}, nil
|
|
}
|
|
|
|
// Get genesis file.
|
|
//
|
|
// ```shell
|
|
// curl 'localhost:26657/genesis'
|
|
// ```
|
|
//
|
|
// ```go
|
|
// client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
|
|
// err := client.Start()
|
|
// if err != nil {
|
|
// // handle error
|
|
// }
|
|
// defer client.Stop()
|
|
// genesis, err := client.Genesis()
|
|
// ```
|
|
//
|
|
// > The above command returns JSON structured like this:
|
|
//
|
|
// ```json
|
|
// {
|
|
// "error": "",
|
|
// "result": {
|
|
// "genesis": {
|
|
// "app_hash": "",
|
|
// "validators": [
|
|
// {
|
|
// "name": "",
|
|
// "power": "10",
|
|
// "pub_key": {
|
|
// "data": "68DFDA7E50F82946E7E8546BED37944A422CD1B831E70DF66BA3B8430593944D",
|
|
// "type": "ed25519"
|
|
// }
|
|
// }
|
|
// ],
|
|
// "chain_id": "test-chain-6UTNIN",
|
|
// "genesis_time": "2017-05-29T15:05:41.671Z"
|
|
// }
|
|
// },
|
|
// "id": "",
|
|
// "jsonrpc": "2.0"
|
|
// }
|
|
// ```
|
|
func Genesis(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
|
|
return &ctypes.ResultGenesis{Genesis: genDoc}, nil
|
|
}
|