7 log "github.com/sirupsen/logrus"
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"
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"`
25 // NetInfo indicate net information
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"`
39 // GetNodeInfo return net information
40 func (a *API) GetNodeInfo() *NetInfo {
41 nodeXPub := cfg.CommonConfig.PrivateKey().XPub()
43 signScript := cfg.FederationPMultiSigScript(cfg.CommonConfig)
44 scriptHash := crypto.Sha256(signScript)
45 address, err := common.NewAddressWitnessScriptHash(scriptHash, consensus.BytomMainNetParams(&consensus.ActiveNetParams))
47 log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("Failed to get federation address.")
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(),
65 if bestPeer := a.sync.BestPeer(); bestPeer != nil {
66 info.HighestBlock = bestPeer.Height
68 if info.CurrentBlock > info.HighestBlock {
69 info.HighestBlock = info.CurrentBlock
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 {
85 // disconnect peer by the peer id
86 func (a *API) disconnectPeerById(peerID string) error {
87 return a.sync.StopPeer(peerID)
90 // connect peer b y net address
91 func (a *API) connectPeerByIpAndPort(ip string, port uint16) (*peers.PeerInfo, error) {
92 netIp := net.ParseIP(ip)
94 return nil, errors.New("invalid ip address")
97 addr := p2p.NewNetAddressIPPort(netIp, port)
99 if err := a.sync.DialPeerWithAddress(addr); err != nil {
100 return nil, errors.Wrap(err, "can not connect to the address")
102 peer := a.getPeerInfoByAddr(addr.String())
104 return nil, errors.New("the peer is disconnected again")
109 // getNetInfo return network information
110 func (a *API) getNetInfo() Response {
111 return NewSuccessResponse(a.GetNodeInfo())
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)
120 // IsProposing return mining status
121 func (a *API) IsMining() bool {
122 return a.blockProposer.IsProposing()
125 // return the peers of current node
126 func (a *API) listPeers() Response {
127 return NewSuccessResponse(a.sync.GetPeerInfos())
131 func (a *API) disconnectPeer(ctx context.Context, ins struct {
132 PeerID string `json:"peer_id"`
134 if err := a.disconnectPeerById(ins.PeerID); err != nil {
135 return NewErrorResponse(err)
137 return NewSuccessResponse(nil)
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"`
145 if peer, err := a.connectPeerByIpAndPort(ins.Ip, ins.Port); err != nil {
146 return NewErrorResponse(err)
148 return NewSuccessResponse(peer)