github.com/koko1123/flow-go-1@v0.29.6/network/channels/channels.go (about)

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package channels
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/koko1123/flow-go-1/model/flow"
    10  )
    11  
    12  // init is called first time this package is imported.
    13  // It creates and initializes channelRoleMap and clusterChannelPrefixRoleMap.
    14  func init() {
    15  	initializeChannelRoleMap()
    16  }
    17  
    18  // channelRoleMap keeps a map between channels and the list of flow roles involved in them.
    19  var channelRoleMap map[Channel]flow.RoleList
    20  
    21  // clusterChannelPrefixRoleMap keeps a map between cluster channel prefixes and the list of flow roles involved in them.
    22  var clusterChannelPrefixRoleMap map[string]flow.RoleList
    23  
    24  // RolesByChannel returns list of flow roles involved in the channel.
    25  // If the given channel is a public channel, the returned list will
    26  // contain all roles.
    27  func RolesByChannel(channel Channel) (flow.RoleList, bool) {
    28  	if IsClusterChannel(channel) {
    29  		return ClusterChannelRoles(channel), true
    30  	}
    31  	if IsPublicChannel(channel) {
    32  		return flow.Roles(), true
    33  	}
    34  	roles, ok := channelRoleMap[channel]
    35  	return roles, ok
    36  }
    37  
    38  // ChannelExists returns true if the channel exists.
    39  func ChannelExists(channel Channel) bool {
    40  	if _, ok := RolesByChannel(channel); ok {
    41  		return true
    42  	}
    43  
    44  	return false
    45  }
    46  
    47  // ChannelsByRole returns a list of all channels the role subscribes to (except cluster-based channels and public channels).
    48  func ChannelsByRole(role flow.Role) ChannelList {
    49  	channels := make(ChannelList, 0)
    50  	for channel, roles := range channelRoleMap {
    51  		if roles.Contains(role) {
    52  			channels = append(channels, channel)
    53  		}
    54  	}
    55  
    56  	return channels
    57  }
    58  
    59  // UniqueChannels returns list of non-cluster channels with a unique RoleList accompanied
    60  // with the list of all cluster channels.
    61  // e.g. if channel X and Y both are non-cluster channels and have role IDs [A,B,C] then only one of them will be in the returned list.
    62  func UniqueChannels(channels ChannelList) ChannelList {
    63  	// uniques keeps the set of unique channels based on their RoleList.
    64  	uniques := make(ChannelList, 0)
    65  	// added keeps track of channels added to uniques for deduplication.
    66  	added := make(map[flow.Identifier]struct{})
    67  
    68  	// a channel is added to uniques if it is either a
    69  	// cluster channel, or no non-cluster channel with the same set of roles
    70  	// has already been added to uniques.
    71  	// We use identifier of RoleList to determine its uniqueness.
    72  	for _, channel := range channels {
    73  		// non-cluster channel deduplicated based identifier of role list
    74  		if !IsClusterChannel(channel) {
    75  			id := channelRoleMap[channel].ID()
    76  			if _, ok := added[id]; ok {
    77  				// a channel with same RoleList already added, hence skips
    78  				continue
    79  			}
    80  			added[id] = struct{}{}
    81  		}
    82  
    83  		uniques = append(uniques, channel)
    84  	}
    85  
    86  	return uniques
    87  }
    88  
    89  // Channels returns all channels that nodes of any role have subscribed to (except cluster-based channels).
    90  func Channels() ChannelList {
    91  	channels := make(ChannelList, 0)
    92  	for channel := range channelRoleMap {
    93  		channels = append(channels, channel)
    94  	}
    95  	channels = append(channels, PublicChannels()...)
    96  
    97  	return channels
    98  }
    99  
   100  // PublicChannels returns all channels that are used on the public network.
   101  func PublicChannels() ChannelList {
   102  	return ChannelList{
   103  		PublicSyncCommittee,
   104  		PublicReceiveBlocks,
   105  	}
   106  }
   107  
   108  // IsPublicChannel returns true if channel is in the public channels list
   109  func IsPublicChannel(channel Channel) bool {
   110  	return PublicChannels().Contains(channel)
   111  }
   112  
   113  // channels
   114  const (
   115  
   116  	// Channels used for testing
   117  	TestNetworkChannel = Channel("test-network")
   118  	TestMetricsChannel = Channel("test-metrics")
   119  
   120  	// Channels for consensus protocols
   121  	ConsensusCommittee     = Channel("consensus-committee")
   122  	ConsensusClusterPrefix = "consensus-cluster" // dynamic channel, use ConsensusCluster function
   123  
   124  	// Channels for protocols actively synchronizing state across nodes
   125  	SyncCommittee     = Channel("sync-committee")
   126  	SyncClusterPrefix = "sync-cluster" // dynamic channel, use SyncCluster function
   127  	SyncExecution     = Channel("sync-execution")
   128  
   129  	// Channels for dkg communication
   130  	DKGCommittee = "dkg-committee"
   131  
   132  	// Channels for actively pushing entities to subscribers
   133  	PushTransactions = Channel("push-transactions")
   134  	PushGuarantees   = Channel("push-guarantees")
   135  	PushBlocks       = Channel("push-blocks")
   136  	PushReceipts     = Channel("push-receipts")
   137  	PushApprovals    = Channel("push-approvals")
   138  
   139  	// Channels for actively requesting missing entities
   140  	RequestCollections       = Channel("request-collections")
   141  	RequestChunks            = Channel("request-chunks")
   142  	RequestReceiptsByBlockID = Channel("request-receipts-by-block-id")
   143  	RequestApprovalsByChunk  = Channel("request-approvals-by-chunk")
   144  
   145  	// Channel aliases to make the code more readable / more robust to errors
   146  	ReceiveTransactions = PushTransactions
   147  	ReceiveGuarantees   = PushGuarantees
   148  	ReceiveBlocks       = PushBlocks
   149  	ReceiveReceipts     = PushReceipts
   150  	ReceiveApprovals    = PushApprovals
   151  
   152  	ProvideCollections       = RequestCollections
   153  	ProvideChunks            = RequestChunks
   154  	ProvideReceiptsByBlockID = RequestReceiptsByBlockID
   155  	ProvideApprovalsByChunk  = RequestApprovalsByChunk
   156  
   157  	// Public network channels
   158  	PublicPushBlocks    = Channel("public-push-blocks")
   159  	PublicReceiveBlocks = PublicPushBlocks
   160  	PublicSyncCommittee = Channel("public-sync-committee")
   161  
   162  	// Execution data service
   163  	ExecutionDataService = Channel("execution-data-service")
   164  )
   165  
   166  // initializeChannelRoleMap initializes an instance of channelRoleMap and populates it
   167  // with the channels and their corresponding list of authorized roles.
   168  // Note: Please update this map, if a new channel is defined or a the roles subscribing to a channel have changed
   169  func initializeChannelRoleMap() {
   170  	channelRoleMap = make(map[Channel]flow.RoleList)
   171  
   172  	// Channels for test
   173  	channelRoleMap[TestNetworkChannel] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus, flow.RoleExecution,
   174  		flow.RoleVerification, flow.RoleAccess}
   175  	channelRoleMap[TestMetricsChannel] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus, flow.RoleExecution,
   176  		flow.RoleVerification, flow.RoleAccess}
   177  
   178  	// Channels for consensus protocols
   179  	channelRoleMap[ConsensusCommittee] = flow.RoleList{flow.RoleConsensus}
   180  
   181  	// Channels for protocols actively synchronizing state across nodes
   182  	channelRoleMap[SyncCommittee] = flow.Roles()
   183  	channelRoleMap[SyncExecution] = flow.RoleList{flow.RoleExecution}
   184  
   185  	// Channels for DKG communication
   186  	channelRoleMap[DKGCommittee] = flow.RoleList{flow.RoleConsensus}
   187  
   188  	// Channels for actively pushing entities to subscribers
   189  	channelRoleMap[PushTransactions] = flow.RoleList{flow.RoleCollection}
   190  	channelRoleMap[PushGuarantees] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus}
   191  	channelRoleMap[PushBlocks] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus, flow.RoleExecution,
   192  		flow.RoleVerification, flow.RoleAccess}
   193  	channelRoleMap[PushReceipts] = flow.RoleList{flow.RoleConsensus, flow.RoleExecution, flow.RoleVerification,
   194  		flow.RoleAccess}
   195  	channelRoleMap[PushApprovals] = flow.RoleList{flow.RoleConsensus, flow.RoleVerification}
   196  
   197  	// Channels for actively requesting missing entities
   198  	channelRoleMap[RequestCollections] = flow.RoleList{flow.RoleCollection, flow.RoleExecution, flow.RoleAccess}
   199  	channelRoleMap[RequestChunks] = flow.RoleList{flow.RoleExecution, flow.RoleVerification}
   200  	channelRoleMap[RequestReceiptsByBlockID] = flow.RoleList{flow.RoleConsensus, flow.RoleExecution}
   201  	channelRoleMap[RequestApprovalsByChunk] = flow.RoleList{flow.RoleConsensus, flow.RoleVerification}
   202  
   203  	// Channel aliases to make the code more readable / more robust to errors
   204  	channelRoleMap[ReceiveGuarantees] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus}
   205  	channelRoleMap[ReceiveBlocks] = flow.RoleList{flow.RoleCollection, flow.RoleConsensus, flow.RoleExecution,
   206  		flow.RoleVerification, flow.RoleAccess}
   207  	channelRoleMap[ReceiveReceipts] = flow.RoleList{flow.RoleConsensus, flow.RoleExecution, flow.RoleVerification,
   208  		flow.RoleAccess}
   209  	channelRoleMap[ReceiveApprovals] = flow.RoleList{flow.RoleConsensus, flow.RoleVerification}
   210  
   211  	channelRoleMap[ProvideCollections] = flow.RoleList{flow.RoleCollection, flow.RoleExecution, flow.RoleAccess}
   212  	channelRoleMap[ProvideChunks] = flow.RoleList{flow.RoleExecution, flow.RoleVerification}
   213  	channelRoleMap[ProvideReceiptsByBlockID] = flow.RoleList{flow.RoleConsensus, flow.RoleExecution}
   214  	channelRoleMap[ProvideApprovalsByChunk] = flow.RoleList{flow.RoleConsensus, flow.RoleVerification}
   215  
   216  	clusterChannelPrefixRoleMap = make(map[string]flow.RoleList)
   217  
   218  	clusterChannelPrefixRoleMap[SyncClusterPrefix] = flow.RoleList{flow.RoleCollection}
   219  	clusterChannelPrefixRoleMap[ConsensusClusterPrefix] = flow.RoleList{flow.RoleCollection}
   220  }
   221  
   222  // ClusterChannelRoles returns the list of roles that are involved in the given cluster-based channel.
   223  func ClusterChannelRoles(clusterChannel Channel) flow.RoleList {
   224  	if prefix, ok := ClusterChannelPrefix(clusterChannel); ok {
   225  		return clusterChannelPrefixRoleMap[prefix]
   226  	}
   227  
   228  	return flow.RoleList{}
   229  }
   230  
   231  // ClusterChannelPrefix returns the cluster channel prefix and true if clusterChannel exists inclusterChannelPrefixRoleMap
   232  func ClusterChannelPrefix(clusterChannel Channel) (string, bool) {
   233  	for prefix := range clusterChannelPrefixRoleMap {
   234  		if strings.HasPrefix(clusterChannel.String(), prefix) {
   235  			return prefix, true
   236  		}
   237  	}
   238  
   239  	return "", false
   240  }
   241  
   242  // IsClusterChannel returns true if channel is cluster-based.
   243  // Currently, only collection nodes are involved in a cluster-based channels.
   244  func IsClusterChannel(channel Channel) bool {
   245  	_, ok := ClusterChannelPrefix(channel)
   246  	return ok
   247  }
   248  
   249  // TopicFromChannel returns the unique LibP2P topic form the channel.
   250  // The channel is made up of name string suffixed with root block id.
   251  // The root block id is used to prevent cross talks between nodes on different sporks.
   252  func TopicFromChannel(channel Channel, rootBlockID flow.Identifier) Topic {
   253  	// skip root block suffix, if this is a cluster specific channel. A cluster specific channel is inherently
   254  	// unique for each epoch
   255  	if IsClusterChannel(channel) {
   256  		return Topic(channel)
   257  	}
   258  	return Topic(fmt.Sprintf("%s/%s", string(channel), rootBlockID.String()))
   259  }
   260  
   261  // TopicsFromChannels returns the unique LibP2P topics form the channels.
   262  func TopicsFromChannels(channels ChannelList, rootBlockID flow.Identifier) []Topic {
   263  	topics := make([]Topic, 0, len(channels))
   264  	for _, channel := range channels {
   265  		topics = append(topics, TopicFromChannel(channel, rootBlockID))
   266  	}
   267  	return topics
   268  }
   269  
   270  func ChannelFromTopic(topic Topic) (Channel, bool) {
   271  	if IsClusterChannel(Channel(topic)) {
   272  		return Channel(topic), true
   273  	}
   274  
   275  	if index := strings.LastIndex(topic.String(), "/"); index != -1 {
   276  		return Channel(topic[:index]), true
   277  	}
   278  
   279  	return "", false
   280  }
   281  
   282  // ConsensusCluster returns a dynamic cluster consensus channel based on
   283  // the chain ID of the cluster in question.
   284  func ConsensusCluster(clusterID flow.ChainID) Channel {
   285  	return Channel(fmt.Sprintf("%s-%s", ConsensusClusterPrefix, clusterID))
   286  }
   287  
   288  // SyncCluster returns a dynamic cluster sync channel based on the chain
   289  // ID of the cluster in question.
   290  func SyncCluster(clusterID flow.ChainID) Channel {
   291  	return Channel(fmt.Sprintf("%s-%s", SyncClusterPrefix, clusterID))
   292  }