OSDN Git Service

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