github.com/amazechain/amc@v0.1.3/internal/p2p/options.go (about)

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