github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/p2p/options.go (about)

     1  package p2p
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"fmt"
     6  	"net"
     7  
     8  	"github.com/libp2p/go-libp2p"
     9  	"github.com/libp2p/go-libp2p-core/peer"
    10  	noise "github.com/libp2p/go-libp2p-noise"
    11  	"github.com/libp2p/go-tcp-transport"
    12  	ma "github.com/multiformats/go-multiaddr"
    13  	"github.com/pkg/errors"
    14  	"github.com/prysmaticlabs/prysm/shared/version"
    15  )
    16  
    17  // buildOptions for the libp2p host.
    18  func (s *Service) buildOptions(ip net.IP, priKey *ecdsa.PrivateKey) []libp2p.Option {
    19  	cfg := s.cfg
    20  	listen, err := multiAddressBuilder(ip.String(), cfg.TCPPort)
    21  	if err != nil {
    22  		log.Fatalf("Failed to p2p listen: %v", err)
    23  	}
    24  	if cfg.LocalIP != "" {
    25  		if net.ParseIP(cfg.LocalIP) == nil {
    26  			log.Fatalf("Invalid local ip provided: %s", cfg.LocalIP)
    27  		}
    28  		listen, err = multiAddressBuilder(cfg.LocalIP, cfg.TCPPort)
    29  		if err != nil {
    30  			log.Fatalf("Failed to p2p listen: %v", err)
    31  		}
    32  	}
    33  	options := []libp2p.Option{
    34  		privKeyOption(priKey),
    35  		libp2p.ListenAddrs(listen),
    36  		libp2p.UserAgent(version.BuildData()),
    37  		libp2p.ConnectionGater(s),
    38  		libp2p.Transport(tcp.NewTCPTransport),
    39  	}
    40  
    41  	options = append(options, libp2p.Security(noise.ID, noise.New))
    42  
    43  	if cfg.EnableUPnP {
    44  		options = append(options, libp2p.NATPortMap()) // Allow to use UPnP
    45  	}
    46  	if cfg.RelayNodeAddr != "" {
    47  		options = append(options, libp2p.AddrsFactory(withRelayAddrs(cfg.RelayNodeAddr)))
    48  	} else {
    49  		// Disable relay if it has not been set.
    50  		options = append(options, libp2p.DisableRelay())
    51  	}
    52  	if cfg.HostAddress != "" {
    53  		options = append(options, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr {
    54  			external, err := multiAddressBuilder(cfg.HostAddress, cfg.TCPPort)
    55  			if err != nil {
    56  				log.WithError(err).Error("Unable to create external multiaddress")
    57  			} else {
    58  				addrs = append(addrs, external)
    59  			}
    60  			return addrs
    61  		}))
    62  	}
    63  	if cfg.HostDNS != "" {
    64  		options = append(options, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr {
    65  			external, err := ma.NewMultiaddr(fmt.Sprintf("/dns4/%s/tcp/%d", cfg.HostDNS, cfg.TCPPort))
    66  			if err != nil {
    67  				log.WithError(err).Error("Unable to create external multiaddress")
    68  			} else {
    69  				addrs = append(addrs, external)
    70  			}
    71  			return addrs
    72  		}))
    73  	}
    74  	// Disable Ping Service.
    75  	options = append(options, libp2p.Ping(false))
    76  	return options
    77  }
    78  
    79  func multiAddressBuilder(ipAddr string, port uint) (ma.Multiaddr, error) {
    80  	parsedIP := net.ParseIP(ipAddr)
    81  	if parsedIP.To4() == nil && parsedIP.To16() == nil {
    82  		return nil, errors.Errorf("invalid ip address provided: %s", ipAddr)
    83  	}
    84  	if parsedIP.To4() != nil {
    85  		return ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", ipAddr, port))
    86  	}
    87  	return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/%d", ipAddr, port))
    88  }
    89  
    90  func multiAddressBuilderWithID(ipAddr, protocol string, port uint, id peer.ID) (ma.Multiaddr, error) {
    91  	parsedIP := net.ParseIP(ipAddr)
    92  	if parsedIP.To4() == nil && parsedIP.To16() == nil {
    93  		return nil, errors.Errorf("invalid ip address provided: %s", ipAddr)
    94  	}
    95  	if id.String() == "" {
    96  		return nil, errors.New("empty peer id given")
    97  	}
    98  	if parsedIP.To4() != nil {
    99  		return ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
   100  	}
   101  	return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
   102  }
   103  
   104  // Adds a private key to the libp2p option if the option was provided.
   105  // If the private key file is missing or cannot be read, or if the
   106  // private key contents cannot be marshaled, an exception is thrown.
   107  func privKeyOption(privkey *ecdsa.PrivateKey) libp2p.Option {
   108  	return func(cfg *libp2p.Config) error {
   109  		log.Debug("ECDSA private key generated")
   110  		return cfg.Apply(libp2p.Identity(convertToInterfacePrivkey(privkey)))
   111  	}
   112  }