github.com/aergoio/aergo@v1.3.1/p2p/p2putil/libp2putil.go (about)

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2putil
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"github.com/aergoio/aergo/internal/network"
    12  	"github.com/aergoio/aergo/p2p/p2pcommon"
    13  	"github.com/aergoio/aergo/types"
    14  	"github.com/libp2p/go-libp2p-core"
    15  	"github.com/libp2p/go-libp2p-core/crypto"
    16  	"github.com/libp2p/go-libp2p-core/test"
    17  	"github.com/multiformats/go-multiaddr"
    18  	"io/ioutil"
    19  	"net"
    20  	"os"
    21  	"path/filepath"
    22  	"strconv"
    23  	"strings"
    24  )
    25  
    26  
    27  // NOTE use only in test
    28  func RandomPeerID() types.PeerID {
    29  	id,_ := test.RandPeerID()
    30  	return id
    31  }
    32  // PeerMetaToMultiAddr make libp2p compatible Multiaddr object from peermeta
    33  func PeerMetaToMultiAddr(m p2pcommon.PeerMeta) (multiaddr.Multiaddr, error) {
    34  	ipAddr, err := network.GetSingleIPAddress(m.IPAddress)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	return types.ToMultiAddr(ipAddr, m.Port)
    39  }
    40  
    41  func FromMultiAddr(targetAddr multiaddr.Multiaddr) (p2pcommon.PeerMeta, error) {
    42  	meta := p2pcommon.PeerMeta{}
    43  	split := strings.Split(targetAddr.String(), "/")
    44  	if len(split) != 7 {
    45  		return meta, fmt.Errorf("invalid NPAddPeer addr format %s", targetAddr.String())
    46  	}
    47  	addrType := split[1]
    48  	if addrType != "ip4" && addrType != "ip6" {
    49  		return meta, fmt.Errorf("invalid NPAddPeer addr type %s", addrType)
    50  	}
    51  	peerAddrString := split[2]
    52  	peerPortString := split[4]
    53  	peerPort, err := strconv.Atoi(peerPortString)
    54  	if err != nil {
    55  		return meta, fmt.Errorf("invalid Peer port %s", peerPortString)
    56  	}
    57  	peerIDString := split[6]
    58  	peerID, err := types.IDB58Decode(peerIDString)
    59  	if err != nil {
    60  		return meta, fmt.Errorf("invalid PeerID %s", peerIDString)
    61  	}
    62  	meta = p2pcommon.PeerMeta{
    63  		ID:        peerID,
    64  		Port:      uint32(peerPort),
    65  		IPAddress: peerAddrString,
    66  	}
    67  	return meta, nil
    68  }
    69  
    70  func FromMultiAddrString(str string) (p2pcommon.PeerMeta, error) {
    71  	ma, err := types.ParseMultiaddrWithResolve(str)
    72  	if err != nil {
    73  		return p2pcommon.PeerMeta{}, err
    74  	}
    75  	return FromMultiAddr(ma)
    76  }
    77  
    78  
    79  func FromMultiAddrStringWithPID(str string, id types.PeerID) (p2pcommon.PeerMeta, error) {
    80  	addr1, err := types.ParseMultiaddrWithResolve(str)
    81  	if err != nil {
    82  		return p2pcommon.PeerMeta{}, err
    83  	}
    84  	pidAddr, err := multiaddr.NewComponent(multiaddr.ProtocolWithCode(multiaddr.P_P2P).Name, id.Pretty())
    85  	if err != nil {
    86  		return p2pcommon.PeerMeta{}, err
    87  	}
    88  	ma := multiaddr.Join(addr1, pidAddr)
    89  	return FromMultiAddr(ma)
    90  }
    91  
    92  // ExtractIPAddress returns ip address from multiaddr. it return null if ma has no ip field.
    93  func ExtractIPAddress(ma multiaddr.Multiaddr) net.IP {
    94  	ipStr, err := ma.ValueForProtocol(multiaddr.P_IP4)
    95  	if err == nil {
    96  		return net.ParseIP(ipStr)
    97  	}
    98  	ipStr, err = ma.ValueForProtocol(multiaddr.P_IP6)
    99  	if err == nil {
   100  		return net.ParseIP(ipStr)
   101  	}
   102  	return nil
   103  }
   104  
   105  func LoadKeyFile(keyFile string) (crypto.PrivKey, crypto.PubKey, error) {
   106  	dat, err := ioutil.ReadFile(keyFile)
   107  	if err == nil {
   108  		priv, err := crypto.UnmarshalPrivateKey(dat)
   109  		if err != nil {
   110  			return nil,nil, fmt.Errorf("invalid keyfile. It's not private key file")
   111  		}
   112  		return priv, priv.GetPublic(), nil
   113  	} else {
   114  		return nil, nil, fmt.Errorf("Invalid keyfile path '"+ keyFile +"'. Check the key file exists.")
   115  	}
   116  }
   117  
   118  func GenerateKeyFile(dir, prefix string) (crypto.PrivKey, crypto.PubKey, error) {
   119  	// invariant: key file must not exists.
   120  	if _, err2 := os.Stat(dir); os.IsNotExist(err2) {
   121  		mkdirErr := os.MkdirAll(dir, os.ModePerm)
   122  		if mkdirErr != nil {
   123  			return nil, nil, mkdirErr
   124  		}
   125  	}
   126  	// file not exist and create new file
   127  	priv, pub, err := crypto.GenerateKeyPair(crypto.Secp256k1, 256)
   128  	if err != nil {
   129  		return nil, nil, err
   130  	}
   131  	err = writeToKeyFiles(priv, pub, dir, prefix)
   132  	if err != nil {
   133  		return nil, nil, fmt.Errorf("Failed to generate files %s.{key,id}: %v", prefix, err.Error())
   134  	}
   135  
   136  	return priv, priv.GetPublic(), nil
   137  }
   138  
   139  
   140  func writeToKeyFiles(priv crypto.PrivKey, pub crypto.PubKey, dir, prefix string) error {
   141  
   142  	pkFile := filepath.Join(dir, prefix+p2pcommon.DefaultPkKeyExt)
   143  //	pubFile := filepath.Join(dir, prefix+".pub")
   144  	idFile := filepath.Join(dir, prefix+p2pcommon.DefaultPeerIDExt)
   145  
   146  	// Write private key file
   147  	pkf, err := os.Create(pkFile)
   148  	if err != nil {
   149  		return err
   150  	}
   151  	pkBytes, err := priv.Bytes()
   152  	if err != nil {
   153  		return err
   154  	}
   155  	pkf.Write(pkBytes)
   156  	pkf.Sync()
   157  
   158  	// Write id file
   159  	idf, err := os.Create(idFile)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	pid, _ := types.IDFromPublicKey(pub)
   164  	idBytes := []byte(types.IDB58Encode(pid))
   165  	idf.Write(idBytes)
   166  	idf.Sync()
   167  	return nil
   168  }
   169  
   170  func ProtocolIDsToString(sli []core.ProtocolID) string {
   171  	sb := bytes.NewBuffer(nil)
   172  	sb.WriteByte('[')
   173  	if len(sli) > 0 {
   174  		stop := len(sli)-1
   175  		for i:=0 ; i<stop; i++ {
   176  			sb.WriteString(string(sli[i]))
   177  			sb.WriteByte(',')
   178  		}
   179  		sb.WriteString(string(sli[stop]))
   180  	}
   181  	sb.WriteByte(']')
   182  	return sb.String()
   183  }