github.com/badrootd/celestia-core@v0.0.0-20240305091328-aa4207a4b25d/rpc/core/net.go (about)

     1  package core
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/badrootd/celestia-core/p2p"
     9  	ctypes "github.com/badrootd/celestia-core/rpc/core/types"
    10  	rpctypes "github.com/badrootd/celestia-core/rpc/jsonrpc/types"
    11  )
    12  
    13  // NetInfo returns network info.
    14  // More: https://docs.cometbft.com/v0.34/rpc/#/Info/net_info
    15  func NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, error) {
    16  	env := GetEnvironment()
    17  	peersList := env.P2PPeers.Peers().List()
    18  	peers := make([]ctypes.Peer, 0, len(peersList))
    19  	for _, peer := range peersList {
    20  		nodeInfo, ok := peer.NodeInfo().(p2p.DefaultNodeInfo)
    21  		if !ok {
    22  			return nil, fmt.Errorf("peer.NodeInfo() is not DefaultNodeInfo")
    23  		}
    24  		peers = append(peers, ctypes.Peer{
    25  			NodeInfo:         nodeInfo,
    26  			IsOutbound:       peer.IsOutbound(),
    27  			ConnectionStatus: peer.Status(),
    28  			RemoteIP:         peer.RemoteIP().String(),
    29  		})
    30  	}
    31  	// TODO: Should we include PersistentPeers and Seeds in here?
    32  	// PRO: useful info
    33  	// CON: privacy
    34  	return &ctypes.ResultNetInfo{
    35  		Listening: env.P2PTransport.IsListening(),
    36  		Listeners: env.P2PTransport.Listeners(),
    37  		NPeers:    len(peers),
    38  		Peers:     peers,
    39  	}, nil
    40  }
    41  
    42  // UnsafeDialSeeds dials the given seeds (comma-separated id@IP:PORT).
    43  func UnsafeDialSeeds(ctx *rpctypes.Context, seeds []string) (*ctypes.ResultDialSeeds, error) {
    44  	if len(seeds) == 0 {
    45  		return &ctypes.ResultDialSeeds{}, errors.New("no seeds provided")
    46  	}
    47  	env := GetEnvironment()
    48  	env.Logger.Info("DialSeeds", "seeds", seeds)
    49  	if err := env.P2PPeers.DialPeersAsync(seeds); err != nil {
    50  		return &ctypes.ResultDialSeeds{}, err
    51  	}
    52  	return &ctypes.ResultDialSeeds{Log: "Dialing seeds in progress. See /net_info for details"}, nil
    53  }
    54  
    55  // UnsafeDialPeers dials the given peers (comma-separated id@IP:PORT),
    56  // optionally making them persistent.
    57  func UnsafeDialPeers(ctx *rpctypes.Context, peers []string, persistent, unconditional, private bool) (
    58  	*ctypes.ResultDialPeers, error) {
    59  	if len(peers) == 0 {
    60  		return &ctypes.ResultDialPeers{}, errors.New("no peers provided")
    61  	}
    62  
    63  	ids, err := getIDs(peers)
    64  	if err != nil {
    65  		return &ctypes.ResultDialPeers{}, err
    66  	}
    67  
    68  	env := GetEnvironment()
    69  	env.Logger.Info("DialPeers", "peers", peers, "persistent",
    70  		persistent, "unconditional", unconditional, "private", private)
    71  
    72  	if persistent {
    73  		if err := env.P2PPeers.AddPersistentPeers(peers); err != nil {
    74  			return &ctypes.ResultDialPeers{}, err
    75  		}
    76  	}
    77  
    78  	if private {
    79  		if err := env.P2PPeers.AddPrivatePeerIDs(ids); err != nil {
    80  			return &ctypes.ResultDialPeers{}, err
    81  		}
    82  	}
    83  
    84  	if unconditional {
    85  		if err := env.P2PPeers.AddUnconditionalPeerIDs(ids); err != nil {
    86  			return &ctypes.ResultDialPeers{}, err
    87  		}
    88  	}
    89  
    90  	if err := env.P2PPeers.DialPeersAsync(peers); err != nil {
    91  		return &ctypes.ResultDialPeers{}, err
    92  	}
    93  
    94  	return &ctypes.ResultDialPeers{Log: "Dialing peers in progress. See /net_info for details"}, nil
    95  }
    96  
    97  // Genesis returns genesis file.
    98  // More: https://docs.cometbft.com/v0.34/rpc/#/Info/genesis
    99  func Genesis(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
   100  	env := GetEnvironment()
   101  	if len(env.genChunks) > 1 {
   102  		return nil, errors.New("genesis response is large, please use the genesis_chunked API instead")
   103  	}
   104  
   105  	return &ctypes.ResultGenesis{Genesis: env.GenDoc}, nil
   106  }
   107  
   108  func GenesisChunked(ctx *rpctypes.Context, chunk uint) (*ctypes.ResultGenesisChunk, error) {
   109  	env := GetEnvironment()
   110  	if env.genChunks == nil {
   111  		return nil, fmt.Errorf("service configuration error, genesis chunks are not initialized")
   112  	}
   113  
   114  	if len(env.genChunks) == 0 {
   115  		return nil, fmt.Errorf("service configuration error, there are no chunks")
   116  	}
   117  
   118  	id := int(chunk)
   119  
   120  	if id > len(env.genChunks)-1 {
   121  		return nil, fmt.Errorf("there are %d chunks, %d is invalid", len(env.genChunks)-1, id)
   122  	}
   123  
   124  	return &ctypes.ResultGenesisChunk{
   125  		TotalChunks: len(env.genChunks),
   126  		ChunkNumber: id,
   127  		Data:        env.genChunks[id],
   128  	}, nil
   129  }
   130  
   131  func getIDs(peers []string) ([]string, error) {
   132  	ids := make([]string, 0, len(peers))
   133  
   134  	for _, peer := range peers {
   135  
   136  		spl := strings.Split(peer, "@")
   137  		if len(spl) != 2 {
   138  			return nil, p2p.ErrNetAddressNoID{Addr: peer}
   139  		}
   140  		ids = append(ids, spl[0])
   141  
   142  	}
   143  	return ids, nil
   144  }