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/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"
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"`
27 // NetInfo indicate net information
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"`
41 // GetNodeInfo return net information
42 func (a *API) GetNodeInfo() *NetInfo {
43 nodeXPub := cfg.CommonConfig.PrivateKey().XPub()
45 federationXPubs := cfg.CommonConfig.Federation.Xpubs
46 fedDerivedPKs := chainkd.XPubKeys(federationXPubs)
47 federationQuorum := cfg.CommonConfig.Federation.Quorum
48 signScript, err := vmutil.P2SPMultiSigProgram(fedDerivedPKs, federationQuorum)
50 log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("Failed to get federation signScript.")
53 scriptHash := crypto.Sha256(signScript)
54 address, err := common.NewAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
56 log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("Failed to get federation address.")
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(),
74 if bestPeer := a.sync.BestPeer(); bestPeer != nil {
75 info.HighestBlock = bestPeer.Height
77 if info.CurrentBlock > info.HighestBlock {
78 info.HighestBlock = info.CurrentBlock
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 {
94 // disconnect peer by the peer id
95 func (a *API) disconnectPeerById(peerID string) error {
96 return a.sync.StopPeer(peerID)
99 // connect peer b y net address
100 func (a *API) connectPeerByIpAndPort(ip string, port uint16) (*peers.PeerInfo, error) {
101 netIp := net.ParseIP(ip)
103 return nil, errors.New("invalid ip address")
106 addr := p2p.NewNetAddressIPPort(netIp, port)
108 if err := a.sync.DialPeerWithAddress(addr); err != nil {
109 return nil, errors.Wrap(err, "can not connect to the address")
111 peer := a.getPeerInfoByAddr(addr.String())
113 return nil, errors.New("the peer is disconnected again")
118 // getNetInfo return network information
119 func (a *API) getNetInfo() Response {
120 return NewSuccessResponse(a.GetNodeInfo())
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)
129 // IsProposing return mining status
130 func (a *API) IsMining() bool {
131 return a.blockProposer.IsProposing()
134 // return the peers of current node
135 func (a *API) listPeers() Response {
136 return NewSuccessResponse(a.sync.GetPeerInfos())
140 func (a *API) disconnectPeer(ctx context.Context, ins struct {
141 PeerID string `json:"peer_id"`
143 if err := a.disconnectPeerById(ins.PeerID); err != nil {
144 return NewErrorResponse(err)
146 return NewSuccessResponse(nil)
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"`
154 if peer, err := a.connectPeerByIpAndPort(ins.Ip, ins.Port); err != nil {
155 return NewErrorResponse(err)
157 return NewSuccessResponse(peer)