OSDN Git Service

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