github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/utils/p2putils.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  
     7  	"github.com/libp2p/go-libp2p/core/peer"
     8  	"github.com/multiformats/go-multiaddr"
     9  	"github.com/onflow/crypto/hash"
    10  
    11  	"github.com/onflow/flow-go/model/flow"
    12  	"github.com/onflow/flow-go/network/channels"
    13  	"github.com/onflow/flow-go/network/internal/p2putils"
    14  )
    15  
    16  // PeerAddressInfo generates the libp2p peer.AddrInfo for the given Flow.Identity.
    17  // A node in flow is defined by a flow.Identity while it is defined by a peer.AddrInfo in libp2p.
    18  //
    19  //	flow.Identity        ---> peer.AddrInfo
    20  //	|-- Address          --->   |-- []multiaddr.Multiaddr
    21  //	|-- NetworkPublicKey --->   |-- ID
    22  func PeerAddressInfo(identity flow.IdentitySkeleton) (peer.AddrInfo, error) {
    23  	ip, port, key, err := p2putils.NetworkingInfo(identity)
    24  	if err != nil {
    25  		return peer.AddrInfo{}, fmt.Errorf("could not translate identity to networking info %s: %w", identity.NodeID.String(), err)
    26  	}
    27  
    28  	addr := MultiAddressStr(ip, port)
    29  	maddr, err := multiaddr.NewMultiaddr(addr)
    30  	if err != nil {
    31  		return peer.AddrInfo{}, err
    32  	}
    33  
    34  	id, err := peer.IDFromPublicKey(key)
    35  	if err != nil {
    36  		return peer.AddrInfo{}, fmt.Errorf("could not extract libp2p id from key:%w", err)
    37  	}
    38  	pInfo := peer.AddrInfo{ID: id, Addrs: []multiaddr.Multiaddr{maddr}}
    39  	return pInfo, err
    40  }
    41  
    42  // PeerInfosFromIDs converts the given flow.Identity to peer.AddrInfo.
    43  // For each identity, if the conversion succeeds, the peer.AddrInfo is included in the result else it is
    44  // included in the error map with the corresponding error
    45  func PeerInfosFromIDs(ids flow.IdentityList) ([]peer.AddrInfo, map[flow.Identifier]error) {
    46  	validIDs := make([]peer.AddrInfo, 0, len(ids))
    47  	invalidIDs := make(map[flow.Identifier]error)
    48  	for _, id := range ids {
    49  		peerInfo, err := PeerAddressInfo(id.IdentitySkeleton)
    50  		if err != nil {
    51  			invalidIDs[id.NodeID] = err
    52  			continue
    53  		}
    54  		validIDs = append(validIDs, peerInfo)
    55  	}
    56  	return validIDs, invalidIDs
    57  }
    58  
    59  // MultiAddressStr receives a node ip and port and returns
    60  // its corresponding Libp2p MultiAddressStr in string format
    61  // in current implementation IP part of the node address is
    62  // either an IP or a dns4.
    63  // https://docs.libp2p.io/concepts/addressing/
    64  func MultiAddressStr(ip, port string) string {
    65  	parsedIP := net.ParseIP(ip)
    66  	if parsedIP != nil {
    67  		// returns parsed ip version of the multi-address
    68  		return fmt.Sprintf("/ip4/%s/tcp/%s", ip, port)
    69  	}
    70  	// could not parse it as an IP address and returns the dns version of the
    71  	// multi-address
    72  	return fmt.Sprintf("/dns4/%s/tcp/%s", ip, port)
    73  }
    74  
    75  // AllowedSubscription returns true if the given role is allowed to subscribe to the topic.
    76  func AllowedSubscription(role flow.Role, topic string) bool {
    77  	channel, ok := channels.ChannelFromTopic(channels.Topic(topic))
    78  	if !ok {
    79  		return false
    80  	}
    81  
    82  	if !role.Valid() {
    83  		// TODO: eventually we should have block proposals relayed on a separate
    84  		// channel on the public network. For now, we need to make sure that
    85  		// full observer nodes can subscribe to the block proposal channel.
    86  		return append(channels.PublicChannels(), channels.ReceiveBlocks).Contains(channel)
    87  	} else {
    88  		if roles, ok := channels.RolesByChannel(channel); ok {
    89  			return roles.Contains(role)
    90  		}
    91  
    92  		return false
    93  	}
    94  }
    95  
    96  // MessageID returns the hash of the given data (used to generate the message ID for pubsub messages).
    97  func MessageID(data []byte) string {
    98  	h := hash.NewSHA3_384()
    99  	_, _ = h.Write(data)
   100  	return h.SumHash().Hex()
   101  }