OSDN Git Service

ac085ffac2c472e5ebe2d9f732c141eaa21aa915
[bytom/vapor.git] / api / nodeinfo.go
1 package api
2
3 import (
4         "context"
5         "net"
6
7         log "github.com/sirupsen/logrus"
8
9         "github.com/vapor/common"
10         cfg "github.com/vapor/config"
11         "github.com/vapor/consensus"
12         "github.com/vapor/crypto"
13         "github.com/vapor/errors"
14         "github.com/vapor/netsync/peers"
15         "github.com/vapor/p2p"
16         "github.com/vapor/version"
17 )
18
19 type VersionInfo struct {
20         Version string `json:"version"`
21         Update  uint16 `json:"update"` // 0: no update; 1: small update; 2: significant update
22         NewVer  string `json:"new_version"`
23 }
24
25 // NetInfo indicate net information
26 type NetInfo struct {
27         Listening    bool         `json:"listening"`
28         Syncing      bool         `json:"syncing"`
29         Mining       bool         `json:"mining"`
30         NodeXPub     string       `json:"node_xpub"`
31         FedAddress   string       `json:"federation_address"`
32         PeerCount    int          `json:"peer_count"`
33         CurrentBlock uint64       `json:"current_block"`
34         HighestBlock uint64       `json:"highest_block"`
35         NetWorkID    string       `json:"network_id"`
36         Version      *VersionInfo `json:"version_info"`
37 }
38
39 // GetNodeInfo return net information
40 func (a *API) GetNodeInfo() *NetInfo {
41         nodeXPub := cfg.CommonConfig.PrivateKey().XPub()
42
43         signScript := cfg.FederationPMultiSigScript(cfg.CommonConfig)
44         scriptHash := crypto.Sha256(signScript)
45         address, err := common.NewAddressWitnessScriptHash(scriptHash, consensus.BytomMainNetParams(&consensus.ActiveNetParams))
46         if err != nil {
47                 log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("Failed to get federation address.")
48         }
49
50         info := &NetInfo{
51                 Listening:    a.sync.IsListening(),
52                 Syncing:      !a.sync.IsCaughtUp(),
53                 Mining:       a.blockProposer.IsProposing(),
54                 NodeXPub:     nodeXPub.String(),
55                 FedAddress:   address.EncodeAddress(),
56                 PeerCount:    a.sync.PeerCount(),
57                 CurrentBlock: a.chain.BestBlockHeight(),
58                 NetWorkID:    a.sync.GetNetwork(),
59                 Version: &VersionInfo{
60                         Version: version.Version,
61                         Update:  version.Status.VersionStatus(),
62                         NewVer:  version.Status.MaxVerSeen(),
63                 },
64         }
65         if bestPeer := a.sync.BestPeer(); bestPeer != nil {
66                 info.HighestBlock = bestPeer.Height
67         }
68         if info.CurrentBlock > info.HighestBlock {
69                 info.HighestBlock = info.CurrentBlock
70         }
71         return info
72 }
73
74 // return the currently connected peers with net address
75 func (a *API) getPeerInfoByAddr(addr string) *peers.PeerInfo {
76         peerInfos := a.sync.GetPeerInfos()
77         for _, peerInfo := range peerInfos {
78                 if peerInfo.RemoteAddr == addr {
79                         return peerInfo
80                 }
81         }
82         return nil
83 }
84
85 // disconnect peer by the peer id
86 func (a *API) disconnectPeerById(peerID string) error {
87         return a.sync.StopPeer(peerID)
88 }
89
90 // connect peer b y net address
91 func (a *API) connectPeerByIpAndPort(ip string, port uint16) (*peers.PeerInfo, error) {
92         netIp := net.ParseIP(ip)
93         if netIp == nil {
94                 return nil, errors.New("invalid ip address")
95         }
96
97         addr := p2p.NewNetAddressIPPort(netIp, port)
98
99         if err := a.sync.DialPeerWithAddress(addr); err != nil {
100                 return nil, errors.Wrap(err, "can not connect to the address")
101         }
102         peer := a.getPeerInfoByAddr(addr.String())
103         if peer == nil {
104                 return nil, errors.New("the peer is disconnected again")
105         }
106         return peer, nil
107 }
108
109 // getNetInfo return network information
110 func (a *API) getNetInfo() Response {
111         return NewSuccessResponse(a.GetNodeInfo())
112 }
113
114 // isMining return is in mining or not
115 func (a *API) isMining() Response {
116         IsMining := map[string]bool{"is_mining": a.IsMining()}
117         return NewSuccessResponse(IsMining)
118 }
119
120 // IsProposing return mining status
121 func (a *API) IsMining() bool {
122         return a.blockProposer.IsProposing()
123 }
124
125 // return the peers of current node
126 func (a *API) listPeers() Response {
127         return NewSuccessResponse(a.sync.GetPeerInfos())
128 }
129
130 // disconnect peer
131 func (a *API) disconnectPeer(ctx context.Context, ins struct {
132         PeerID string `json:"peer_id"`
133 }) Response {
134         if err := a.disconnectPeerById(ins.PeerID); err != nil {
135                 return NewErrorResponse(err)
136         }
137         return NewSuccessResponse(nil)
138 }
139
140 // connect peer by ip and port
141 func (a *API) connectPeer(ctx context.Context, ins struct {
142         Ip   string `json:"ip"`
143         Port uint16 `json:"port"`
144 }) Response {
145         if peer, err := a.connectPeerByIpAndPort(ins.Ip, ins.Port); err != nil {
146                 return NewErrorResponse(err)
147         } else {
148                 return NewSuccessResponse(peer)
149         }
150 }