package p2p import ( "context" "fmt" "sync" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" dht "github.com/libp2p/go-libp2p-kad-dht" ma "github.com/multiformats/go-multiaddr" ) const Protocol = "/hyprspace/0.0.1" func CreateNode(ctx context.Context, inputKey string, handler network.StreamHandler) (node host.Host, dhtOut *dht.IpfsDHT, err error) { // Unmarshall Private Key privateKey, err := crypto.UnmarshalPrivateKey([]byte(inputKey)) if err != nil { return } // Create libp2p node node, err = libp2p.New(ctx, libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", 8001)), libp2p.Identity(privateKey), ) if err != nil { return } // Setup Hyprspace Stream Handler node.SetStreamHandler(Protocol, handler) // Create DHT Subsystem dhtOut, err = dht.New(ctx, node) if err != nil { return } // Define Bootstrap Nodes. peers := []string{ "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt", "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", "/ip4/104.131.131.82/udp/4001/quic/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb", } // Convert Bootstap Nodes into usable addresses. BootstrapPeers := make(map[peer.ID]*peer.AddrInfo, len(peers)) for _, addrStr := range peers { addr, err := ma.NewMultiaddr(addrStr) if err != nil { return node, dhtOut, err } pii, err := peer.AddrInfoFromP2pAddr(addr) if err != nil { return node, dhtOut, err } pi, ok := BootstrapPeers[pii.ID] if !ok { pi = &peer.AddrInfo{ID: pii.ID} BootstrapPeers[pi.ID] = pi } pi.Addrs = append(pi.Addrs, pii.Addrs...) } // Let's connect to the bootstrap nodes first. They will tell us about the // other nodes in the network. var wg sync.WaitGroup count := 0 wg.Add(len(BootstrapPeers)) for _, peerInfo := range BootstrapPeers { go func(peerInfo *peer.AddrInfo) { defer wg.Done() err := node.Connect(ctx, *peerInfo) if err == nil { count++ } }(peerInfo) } wg.Wait() err = dhtOut.Bootstrap(ctx) return }