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 }