github.com/celestiaorg/celestia-node@v0.15.0-beta.1/nodebuilder/p2p/cmd/p2p.go (about)

     1  package cmd
     2  
     3  import (
     4  	"github.com/libp2p/go-libp2p/core/metrics"
     5  	"github.com/libp2p/go-libp2p/core/network"
     6  	"github.com/libp2p/go-libp2p/core/peer"
     7  	"github.com/libp2p/go-libp2p/core/protocol"
     8  	ma2 "github.com/multiformats/go-multiaddr"
     9  	"github.com/spf13/cobra"
    10  
    11  	cmdnode "github.com/celestiaorg/celestia-node/cmd"
    12  )
    13  
    14  type peerInfo struct {
    15  	ID       string   `json:"id"`
    16  	PeerAddr []string `json:"peer_addr"`
    17  }
    18  
    19  func init() {
    20  	Cmd.AddCommand(infoCmd,
    21  		peersCmd,
    22  		peerInfoCmd,
    23  		connectCmd,
    24  		closePeerCmd,
    25  		connectednessCmd,
    26  		natStatusCmd,
    27  		blockPeerCmd,
    28  		unblockPeerCmd,
    29  		blockedPeersCmd,
    30  		protectCmd,
    31  		unprotectCmd,
    32  		protectedCmd,
    33  		bandwidthStatsCmd,
    34  		peerBandwidthCmd,
    35  		bandwidthForProtocolCmd,
    36  		pubsubPeersCmd,
    37  	)
    38  }
    39  
    40  var Cmd = &cobra.Command{
    41  	Use:               "p2p [command]",
    42  	Short:             "Allows interaction with the P2P Module via JSON-RPC",
    43  	Args:              cobra.NoArgs,
    44  	PersistentPreRunE: cmdnode.InitClient,
    45  }
    46  
    47  var infoCmd = &cobra.Command{
    48  	Use:   "info",
    49  	Short: "Gets the node's peer info (peer id and multiaddresses)",
    50  	Args:  cobra.NoArgs,
    51  	RunE: func(cmd *cobra.Command, args []string) error {
    52  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
    53  		if err != nil {
    54  			return err
    55  		}
    56  		defer client.Close()
    57  
    58  		info, err := client.P2P.Info(cmd.Context())
    59  
    60  		formatter := func(data interface{}) interface{} {
    61  			peerAdd := data.(peer.AddrInfo)
    62  			ma := make([]string, len(info.Addrs))
    63  			for i := range peerAdd.Addrs {
    64  				ma[i] = peerAdd.Addrs[i].String()
    65  			}
    66  
    67  			return peerInfo{
    68  				ID:       peerAdd.ID.String(),
    69  				PeerAddr: ma,
    70  			}
    71  		}
    72  		return cmdnode.PrintOutput(info, err, formatter)
    73  	},
    74  }
    75  
    76  var peersCmd = &cobra.Command{
    77  	Use:   "peers",
    78  	Short: "Lists the peers we are connected to",
    79  	Args:  cobra.NoArgs,
    80  	RunE: func(cmd *cobra.Command, args []string) error {
    81  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
    82  		if err != nil {
    83  			return err
    84  		}
    85  		defer client.Close()
    86  
    87  		result, err := client.P2P.Peers(cmd.Context())
    88  		peers := make([]string, len(result))
    89  		for i, peer := range result {
    90  			peers[i] = peer.String()
    91  		}
    92  
    93  		formatter := func(data interface{}) interface{} {
    94  			conPeers := data.([]string)
    95  			return struct {
    96  				Peers []string `json:"peers"`
    97  			}{
    98  				Peers: conPeers,
    99  			}
   100  		}
   101  		return cmdnode.PrintOutput(peers, err, formatter)
   102  	},
   103  }
   104  
   105  var peerInfoCmd = &cobra.Command{
   106  	Use:   "peer-info [param]",
   107  	Short: "Gets PeerInfo for a given peer",
   108  	Args:  cobra.ExactArgs(1),
   109  	RunE: func(cmd *cobra.Command, args []string) error {
   110  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   111  		if err != nil {
   112  			return err
   113  		}
   114  		defer client.Close()
   115  
   116  		pid, err := peer.Decode(args[0])
   117  		if err != nil {
   118  			return err
   119  		}
   120  		info, err := client.P2P.PeerInfo(cmd.Context(), pid)
   121  		formatter := func(data interface{}) interface{} {
   122  			peerAdd := data.(peer.AddrInfo)
   123  			ma := make([]string, len(info.Addrs))
   124  			for i := range peerAdd.Addrs {
   125  				ma[i] = peerAdd.Addrs[i].String()
   126  			}
   127  
   128  			return peerInfo{
   129  				ID:       peerAdd.ID.String(),
   130  				PeerAddr: ma,
   131  			}
   132  		}
   133  		return cmdnode.PrintOutput(info, err, formatter)
   134  	},
   135  }
   136  
   137  var connectCmd = &cobra.Command{
   138  	Use:   "connect [peer.ID, address]",
   139  	Short: "Establishes a connection with the given peer",
   140  	Args:  cobra.ExactArgs(2),
   141  	RunE: func(cmd *cobra.Command, args []string) error {
   142  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   143  		if err != nil {
   144  			return err
   145  		}
   146  		defer client.Close()
   147  
   148  		pid, err := peer.Decode(args[0])
   149  		if err != nil {
   150  			return err
   151  		}
   152  
   153  		ma, err := ma2.NewMultiaddr(args[1])
   154  		if err != nil {
   155  			return err
   156  		}
   157  
   158  		peerInfo := peer.AddrInfo{
   159  			ID:    pid,
   160  			Addrs: []ma2.Multiaddr{ma},
   161  		}
   162  
   163  		err = client.P2P.Connect(cmd.Context(), peerInfo)
   164  		if err != nil {
   165  			return cmdnode.PrintOutput(nil, err, nil)
   166  		}
   167  		return connectednessCmd.RunE(cmd, args)
   168  	},
   169  }
   170  
   171  var closePeerCmd = &cobra.Command{
   172  	Use:   "close-peer [peer.ID]",
   173  	Short: "Closes the connection with the given peer",
   174  	Args:  cobra.ExactArgs(1),
   175  	RunE: func(cmd *cobra.Command, args []string) error {
   176  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   177  		if err != nil {
   178  			return err
   179  		}
   180  		defer client.Close()
   181  
   182  		pid, err := peer.Decode(args[0])
   183  		if err != nil {
   184  			return err
   185  		}
   186  
   187  		err = client.P2P.ClosePeer(cmd.Context(), pid)
   188  		if err != nil {
   189  			return cmdnode.PrintOutput(nil, err, nil)
   190  		}
   191  		return connectednessCmd.RunE(cmd, args)
   192  	},
   193  }
   194  
   195  var connectednessCmd = &cobra.Command{
   196  	Use:   "connectedness [peer.ID]",
   197  	Short: "Checks the connection state between current and given peers",
   198  	Args:  cobra.ExactArgs(1),
   199  	RunE: func(cmd *cobra.Command, args []string) error {
   200  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   201  		if err != nil {
   202  			return err
   203  		}
   204  		defer client.Close()
   205  
   206  		pid, err := peer.Decode(args[0])
   207  		if err != nil {
   208  			return err
   209  		}
   210  
   211  		con, err := client.P2P.Connectedness(cmd.Context(), pid)
   212  
   213  		formatter := func(data interface{}) interface{} {
   214  			conn := data.(network.Connectedness)
   215  			return struct {
   216  				ConnectionState string `json:"connection_state"`
   217  			}{
   218  				ConnectionState: conn.String(),
   219  			}
   220  		}
   221  		return cmdnode.PrintOutput(con, err, formatter)
   222  	},
   223  }
   224  
   225  var natStatusCmd = &cobra.Command{
   226  	Use:   "nat-status",
   227  	Short: "Gets the current NAT status",
   228  	Args:  cobra.NoArgs,
   229  	RunE: func(cmd *cobra.Command, args []string) error {
   230  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   231  		if err != nil {
   232  			return err
   233  		}
   234  		defer client.Close()
   235  
   236  		r, err := client.P2P.NATStatus(cmd.Context())
   237  
   238  		formatter := func(data interface{}) interface{} {
   239  			rr := data.(network.Reachability)
   240  			return struct {
   241  				Reachability string `json:"reachability"`
   242  			}{
   243  				Reachability: rr.String(),
   244  			}
   245  		}
   246  		return cmdnode.PrintOutput(r, err, formatter)
   247  	},
   248  }
   249  
   250  var blockPeerCmd = &cobra.Command{
   251  	Use:   "block-peer [peer.ID]",
   252  	Short: "Blocks the given peer",
   253  	Args:  cobra.ExactArgs(1),
   254  	RunE: func(cmd *cobra.Command, args []string) error {
   255  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   256  		if err != nil {
   257  			return err
   258  		}
   259  		defer client.Close()
   260  
   261  		pid, err := peer.Decode(args[0])
   262  		if err != nil {
   263  			return err
   264  		}
   265  
   266  		err = client.P2P.BlockPeer(cmd.Context(), pid)
   267  
   268  		formatter := func(data interface{}) interface{} {
   269  			err, ok := data.(error)
   270  			blocked := false
   271  			if !ok {
   272  				blocked = true
   273  			}
   274  			return struct {
   275  				Blocked bool   `json:"blocked"`
   276  				Peer    string `json:"peer"`
   277  				Reason  error  `json:"reason,omitempty"`
   278  			}{
   279  				Blocked: blocked,
   280  				Peer:    args[0],
   281  				Reason:  err,
   282  			}
   283  		}
   284  		return cmdnode.PrintOutput(err, nil, formatter)
   285  	},
   286  }
   287  
   288  var unblockPeerCmd = &cobra.Command{
   289  	Use:   "unblock-peer [peer.ID]",
   290  	Short: "Unblocks the given peer",
   291  	Args:  cobra.ExactArgs(1),
   292  	RunE: func(cmd *cobra.Command, args []string) error {
   293  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   294  		if err != nil {
   295  			return err
   296  		}
   297  		defer client.Close()
   298  
   299  		pid, err := peer.Decode(args[0])
   300  		if err != nil {
   301  			return err
   302  		}
   303  
   304  		err = client.P2P.UnblockPeer(cmd.Context(), pid)
   305  
   306  		formatter := func(data interface{}) interface{} {
   307  			err, ok := data.(error)
   308  			unblocked := false
   309  			if !ok {
   310  				unblocked = true
   311  			}
   312  
   313  			return struct {
   314  				Unblocked bool   `json:"unblocked"`
   315  				Peer      string `json:"peer"`
   316  				Reason    error  `json:"reason,omitempty"`
   317  			}{
   318  				Unblocked: unblocked,
   319  				Peer:      args[0],
   320  				Reason:    err,
   321  			}
   322  		}
   323  		return cmdnode.PrintOutput(err, nil, formatter)
   324  	},
   325  }
   326  
   327  var blockedPeersCmd = &cobra.Command{
   328  	Use:   "blocked-peers",
   329  	Short: "Lists the node's blocked peers",
   330  	Args:  cobra.NoArgs,
   331  	RunE: func(cmd *cobra.Command, args []string) error {
   332  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   333  		if err != nil {
   334  			return err
   335  		}
   336  		defer client.Close()
   337  
   338  		list, err := client.P2P.ListBlockedPeers(cmd.Context())
   339  
   340  		pids := make([]string, len(list))
   341  		for i, peer := range list {
   342  			pids[i] = peer.String()
   343  		}
   344  
   345  		formatter := func(data interface{}) interface{} {
   346  			peers := data.([]string)
   347  			return struct {
   348  				Peers []string `json:"peers"`
   349  			}{
   350  				Peers: peers,
   351  			}
   352  		}
   353  		return cmdnode.PrintOutput(pids, err, formatter)
   354  	},
   355  }
   356  
   357  var protectCmd = &cobra.Command{
   358  	Use:   "protect [peer.ID, tag]",
   359  	Short: "Protects the given peer from being pruned by the given tag",
   360  	Args:  cobra.ExactArgs(2),
   361  	RunE: func(cmd *cobra.Command, args []string) error {
   362  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   363  		if err != nil {
   364  			return err
   365  		}
   366  		defer client.Close()
   367  
   368  		pid, err := peer.Decode(args[0])
   369  		if err != nil {
   370  			return err
   371  		}
   372  
   373  		err = client.P2P.Protect(cmd.Context(), pid, args[1])
   374  
   375  		formatter := func(data interface{}) interface{} {
   376  			err, ok := data.(error)
   377  			protected := false
   378  			if !ok {
   379  				protected = true
   380  			}
   381  			return struct {
   382  				Protected bool   `json:"protected"`
   383  				Peer      string `json:"peer"`
   384  				Reason    error  `json:"reason,omitempty"`
   385  			}{
   386  				Protected: protected,
   387  				Peer:      args[0],
   388  				Reason:    err,
   389  			}
   390  		}
   391  		return cmdnode.PrintOutput(err, nil, formatter)
   392  	},
   393  }
   394  
   395  var unprotectCmd = &cobra.Command{
   396  	Use:   "unprotect [peer.ID, tag]",
   397  	Short: "Removes protection from the given peer.",
   398  	Long: "Removes a protection that may have been placed on a peer, under the specified tag." +
   399  		"The return value indicates whether the peer continues to be protected after this call, by way of a different tag",
   400  	Args: cobra.ExactArgs(2),
   401  	RunE: func(cmd *cobra.Command, args []string) error {
   402  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   403  		if err != nil {
   404  			return err
   405  		}
   406  		defer client.Close()
   407  
   408  		pid, err := peer.Decode(args[0])
   409  		if err != nil {
   410  			return err
   411  		}
   412  
   413  		_, err = client.P2P.Unprotect(cmd.Context(), pid, args[1])
   414  
   415  		formatter := func(data interface{}) interface{} {
   416  			err, ok := data.(error)
   417  			unprotected := false
   418  			if !ok {
   419  				unprotected = true
   420  			}
   421  			return struct {
   422  				Unprotected bool   `json:"unprotected"`
   423  				Peer        string `json:"peer"`
   424  				Reason      error  `json:"reason,omitempty"`
   425  			}{
   426  				Unprotected: unprotected,
   427  				Peer:        args[0],
   428  				Reason:      err,
   429  			}
   430  		}
   431  		return cmdnode.PrintOutput(err, nil, formatter)
   432  	},
   433  }
   434  
   435  var protectedCmd = &cobra.Command{
   436  	Use:   "protected [peer.ID, tag]",
   437  	Short: "Ensures that a given peer is protected under a specific tag",
   438  	Args:  cobra.ExactArgs(2),
   439  	RunE: func(cmd *cobra.Command, args []string) error {
   440  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   441  		if err != nil {
   442  			return err
   443  		}
   444  		defer client.Close()
   445  
   446  		pid, err := peer.Decode(args[0])
   447  		if err != nil {
   448  			return err
   449  		}
   450  
   451  		result, err := client.P2P.IsProtected(cmd.Context(), pid, args[1])
   452  		return cmdnode.PrintOutput(result, err, nil)
   453  	},
   454  }
   455  
   456  type bandwidthStats struct {
   457  	TotalIn  int64   `json:"total_in"`
   458  	TotalOut int64   `json:"total_out"`
   459  	RateIn   float64 `json:"rate_in"`
   460  	RateOut  float64 `json:"rate_out"`
   461  }
   462  
   463  var bandwidthStatsCmd = &cobra.Command{
   464  	Use:   "bandwidth-stats",
   465  	Short: "Provides metrics for current peer.",
   466  	Long: "Get stats struct with bandwidth metrics for all data sent/" +
   467  		"received by the local peer, regardless of protocol or remote peer IDs",
   468  	Args: cobra.NoArgs,
   469  	RunE: func(cmd *cobra.Command, args []string) error {
   470  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   471  		if err != nil {
   472  			return err
   473  		}
   474  		defer client.Close()
   475  
   476  		result, err := client.P2P.BandwidthStats(cmd.Context())
   477  
   478  		formatter := func(data interface{}) interface{} {
   479  			stats := data.(metrics.Stats)
   480  			return bandwidthStats{
   481  				TotalIn:  stats.TotalIn,
   482  				TotalOut: stats.TotalOut,
   483  				RateIn:   stats.RateIn,
   484  				RateOut:  stats.RateOut,
   485  			}
   486  		}
   487  		return cmdnode.PrintOutput(result, err, formatter)
   488  	},
   489  }
   490  
   491  var peerBandwidthCmd = &cobra.Command{
   492  	Use:   "peer-bandwidth [peer.ID]",
   493  	Short: "Gets stats struct with bandwidth metrics associated with the given peer.ID",
   494  	Args:  cobra.ExactArgs(1),
   495  	RunE: func(cmd *cobra.Command, args []string) error {
   496  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   497  		if err != nil {
   498  			return err
   499  		}
   500  		defer client.Close()
   501  
   502  		pid, err := peer.Decode(args[0])
   503  		if err != nil {
   504  			return err
   505  		}
   506  
   507  		result, err := client.P2P.BandwidthForPeer(cmd.Context(), pid)
   508  
   509  		formatter := func(data interface{}) interface{} {
   510  			stats := data.(metrics.Stats)
   511  			return bandwidthStats{
   512  				TotalIn:  stats.TotalIn,
   513  				TotalOut: stats.TotalOut,
   514  				RateIn:   stats.RateIn,
   515  				RateOut:  stats.RateOut,
   516  			}
   517  		}
   518  		return cmdnode.PrintOutput(result, err, formatter)
   519  	},
   520  }
   521  
   522  var bandwidthForProtocolCmd = &cobra.Command{
   523  	Use:   "protocol-bandwidth [protocol.ID]",
   524  	Short: "Gets stats struct with bandwidth metrics associated with the given protocol.ID",
   525  	Args:  cobra.ExactArgs(1),
   526  	RunE: func(cmd *cobra.Command, args []string) error {
   527  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   528  		if err != nil {
   529  			return err
   530  		}
   531  		defer client.Close()
   532  
   533  		result, err := client.P2P.BandwidthForProtocol(cmd.Context(), protocol.ID(args[0]))
   534  
   535  		formatter := func(data interface{}) interface{} {
   536  			stats := data.(metrics.Stats)
   537  			return bandwidthStats{
   538  				TotalIn:  stats.TotalIn,
   539  				TotalOut: stats.TotalOut,
   540  				RateIn:   stats.RateIn,
   541  				RateOut:  stats.RateOut,
   542  			}
   543  		}
   544  		return cmdnode.PrintOutput(result, err, formatter)
   545  	},
   546  }
   547  
   548  var pubsubPeersCmd = &cobra.Command{
   549  	Use:   "pubsub-peers [topic]",
   550  	Short: "Lists the peers we are connected to in the given topic",
   551  	Args:  cobra.ExactArgs(1),
   552  	RunE: func(cmd *cobra.Command, args []string) error {
   553  		client, err := cmdnode.ParseClientFromCtx(cmd.Context())
   554  		if err != nil {
   555  			return err
   556  		}
   557  		defer client.Close()
   558  
   559  		result, err := client.P2P.PubSubPeers(cmd.Context(), args[0])
   560  		peers := make([]string, len(result))
   561  
   562  		for i, peer := range result {
   563  			peers[i] = peer.String()
   564  		}
   565  
   566  		formatter := func(data interface{}) interface{} {
   567  			conPeers := data.([]string)
   568  			return struct {
   569  				Peers []string `json:"peers"`
   570  			}{
   571  				Peers: conPeers,
   572  			}
   573  		}
   574  		return cmdnode.PrintOutput(peers, err, formatter)
   575  	},
   576  }