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 }