github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/multichannel/registrar.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 // Package multichannel tracks the channel resources for the orderer. It initially 8 // loads the set of existing channels, and provides an interface for users of these 9 // channels to retrieve them, or create new ones. 10 package multichannel 11 12 import ( 13 "fmt" 14 "sync" 15 16 cb "github.com/hyperledger/fabric-protos-go/common" 17 ab "github.com/hyperledger/fabric-protos-go/orderer" 18 "github.com/hyperledger/fabric/bccsp" 19 "github.com/hyperledger/fabric/common/channelconfig" 20 "github.com/hyperledger/fabric/common/configtx" 21 "github.com/hyperledger/fabric/common/flogging" 22 "github.com/hyperledger/fabric/common/ledger/blockledger" 23 "github.com/hyperledger/fabric/common/metrics" 24 "github.com/hyperledger/fabric/internal/pkg/identity" 25 "github.com/hyperledger/fabric/orderer/common/blockcutter" 26 "github.com/hyperledger/fabric/orderer/common/localconfig" 27 "github.com/hyperledger/fabric/orderer/common/msgprocessor" 28 "github.com/hyperledger/fabric/orderer/consensus" 29 "github.com/hyperledger/fabric/protoutil" 30 "github.com/pkg/errors" 31 ) 32 33 const ( 34 msgVersion = int32(0) 35 epoch = 0 36 ) 37 38 var logger = flogging.MustGetLogger("orderer.commmon.multichannel") 39 40 // checkResources makes sure that the channel config is compatible with this binary and logs sanity checks 41 func checkResources(res channelconfig.Resources) error { 42 channelconfig.LogSanityChecks(res) 43 oc, ok := res.OrdererConfig() 44 if !ok { 45 return errors.New("config does not contain orderer config") 46 } 47 if err := oc.Capabilities().Supported(); err != nil { 48 return errors.Wrapf(err, "config requires unsupported orderer capabilities: %s", err) 49 } 50 if err := res.ChannelConfig().Capabilities().Supported(); err != nil { 51 return errors.Wrapf(err, "config requires unsupported channel capabilities: %s", err) 52 } 53 return nil 54 } 55 56 // checkResourcesOrPanic invokes checkResources and panics if an error is returned 57 func checkResourcesOrPanic(res channelconfig.Resources) { 58 if err := checkResources(res); err != nil { 59 logger.Panicf("[channel %s] %s", res.ConfigtxValidator().ChannelID(), err) 60 } 61 } 62 63 type mutableResources interface { 64 channelconfig.Resources 65 Update(*channelconfig.Bundle) 66 } 67 68 type configResources struct { 69 mutableResources 70 bccsp bccsp.BCCSP 71 } 72 73 func (cr *configResources) CreateBundle(channelID string, config *cb.Config) (*channelconfig.Bundle, error) { 74 return channelconfig.NewBundle(channelID, config, cr.bccsp) 75 } 76 77 func (cr *configResources) Update(bndl *channelconfig.Bundle) { 78 checkResourcesOrPanic(bndl) 79 cr.mutableResources.Update(bndl) 80 } 81 82 func (cr *configResources) SharedConfig() channelconfig.Orderer { 83 oc, ok := cr.OrdererConfig() 84 if !ok { 85 logger.Panicf("[channel %s] has no orderer configuration", cr.ConfigtxValidator().ChannelID()) 86 } 87 return oc 88 } 89 90 type ledgerResources struct { 91 *configResources 92 blockledger.ReadWriter 93 } 94 95 // Registrar serves as a point of access and control for the individual channel resources. 96 type Registrar struct { 97 config localconfig.TopLevel 98 lock sync.RWMutex 99 chains map[string]*ChainSupport 100 101 consenters map[string]consensus.Consenter 102 ledgerFactory blockledger.Factory 103 signer identity.SignerSerializer 104 blockcutterMetrics *blockcutter.Metrics 105 systemChannelID string 106 systemChannel *ChainSupport 107 templator msgprocessor.ChannelConfigTemplator 108 callbacks []channelconfig.BundleActor 109 bccsp bccsp.BCCSP 110 } 111 112 // ConfigBlock retrieves the last configuration block from the given ledger. 113 // Panics on failure. 114 func ConfigBlock(reader blockledger.Reader) *cb.Block { 115 lastBlock := blockledger.GetBlock(reader, reader.Height()-1) 116 index, err := protoutil.GetLastConfigIndexFromBlock(lastBlock) 117 if err != nil { 118 logger.Panicf("Chain did not have appropriately encoded last config in its latest block: %s", err) 119 } 120 configBlock := blockledger.GetBlock(reader, index) 121 if configBlock == nil { 122 logger.Panicf("Config block does not exist") 123 } 124 125 return configBlock 126 } 127 128 func configTx(reader blockledger.Reader) *cb.Envelope { 129 return protoutil.ExtractEnvelopeOrPanic(ConfigBlock(reader), 0) 130 } 131 132 // NewRegistrar produces an instance of a *Registrar. 133 func NewRegistrar( 134 config localconfig.TopLevel, 135 ledgerFactory blockledger.Factory, 136 signer identity.SignerSerializer, 137 metricsProvider metrics.Provider, 138 bccsp bccsp.BCCSP, 139 callbacks ...channelconfig.BundleActor, 140 ) *Registrar { 141 r := &Registrar{ 142 config: config, 143 chains: make(map[string]*ChainSupport), 144 ledgerFactory: ledgerFactory, 145 signer: signer, 146 blockcutterMetrics: blockcutter.NewMetrics(metricsProvider), 147 callbacks: callbacks, 148 bccsp: bccsp, 149 } 150 151 return r 152 } 153 154 func (r *Registrar) Initialize(consenters map[string]consensus.Consenter) { 155 r.consenters = consenters 156 existingChannels := r.ledgerFactory.ChannelIDs() 157 158 for _, channelID := range existingChannels { 159 rl, err := r.ledgerFactory.GetOrCreate(channelID) 160 if err != nil { 161 logger.Panicf("Ledger factory reported channelID %s but could not retrieve it: %s", channelID, err) 162 } 163 configTx := configTx(rl) 164 if configTx == nil { 165 logger.Panic("Programming error, configTx should never be nil here") 166 } 167 ledgerResources := r.newLedgerResources(configTx) 168 channelID := ledgerResources.ConfigtxValidator().ChannelID() 169 170 if _, ok := ledgerResources.ConsortiumsConfig(); ok { 171 if r.systemChannelID != "" { 172 logger.Panicf("There appear to be two system channels %s and %s", r.systemChannelID, channelID) 173 } 174 175 chain := newChainSupport( 176 r, 177 ledgerResources, 178 r.consenters, 179 r.signer, 180 r.blockcutterMetrics, 181 r.bccsp, 182 ) 183 r.templator = msgprocessor.NewDefaultTemplator(chain, r.bccsp) 184 chain.Processor = msgprocessor.NewSystemChannel( 185 chain, 186 r.templator, 187 msgprocessor.CreateSystemChannelFilters(r.config, r, chain, chain.MetadataValidator), 188 r.bccsp, 189 ) 190 191 // Retrieve genesis block to log its hash. See FAB-5450 for the purpose 192 iter, pos := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Oldest{Oldest: &ab.SeekOldest{}}}) 193 defer iter.Close() 194 if pos != uint64(0) { 195 logger.Panicf("Error iterating over system channel: '%s', expected position 0, got %d", channelID, pos) 196 } 197 genesisBlock, status := iter.Next() 198 if status != cb.Status_SUCCESS { 199 logger.Panicf("Error reading genesis block of system channel '%s'", channelID) 200 } 201 logger.Infof("Starting system channel '%s' with genesis block hash %x and orderer type %s", 202 channelID, protoutil.BlockHeaderHash(genesisBlock.Header), chain.SharedConfig().ConsensusType()) 203 204 r.chains[channelID] = chain 205 r.systemChannelID = channelID 206 r.systemChannel = chain 207 // We delay starting this channel, as it might try to copy and replace the channels map via newChannel before the map is fully built 208 defer chain.start() 209 } else { 210 logger.Debugf("Starting channel: %s", channelID) 211 chain := newChainSupport( 212 r, 213 ledgerResources, 214 r.consenters, 215 r.signer, 216 r.blockcutterMetrics, 217 r.bccsp, 218 ) 219 r.chains[channelID] = chain 220 chain.start() 221 } 222 223 } 224 225 if r.systemChannelID == "" { 226 logger.Warning("registrar initializing without a system channel") 227 } 228 } 229 230 // SystemChannelID returns the ChannelID for the system channel. 231 func (r *Registrar) SystemChannelID() string { 232 return r.systemChannelID 233 } 234 235 // BroadcastChannelSupport returns the message channel header, whether the message is a config update 236 // and the channel resources for a message or an error if the message is not a message which can 237 // be processed directly (like CONFIG and ORDERER_TRANSACTION messages) 238 func (r *Registrar) BroadcastChannelSupport(msg *cb.Envelope) (*cb.ChannelHeader, bool, *ChainSupport, error) { 239 chdr, err := protoutil.ChannelHeader(msg) 240 if err != nil { 241 return nil, false, nil, fmt.Errorf("could not determine channel ID: %s", err) 242 } 243 244 cs := r.GetChain(chdr.ChannelId) 245 // New channel creation 246 if cs == nil { 247 if r.systemChannel == nil { 248 return nil, false, nil, errors.New("channel creation request not allowed because the orderer system channel is not yet defined") 249 } 250 cs = r.systemChannel 251 } 252 253 isConfig := false 254 switch cs.ClassifyMsg(chdr) { 255 case msgprocessor.ConfigUpdateMsg: 256 isConfig = true 257 case msgprocessor.ConfigMsg: 258 return chdr, false, nil, errors.New("message is of type that cannot be processed directly") 259 default: 260 } 261 262 return chdr, isConfig, cs, nil 263 } 264 265 // GetChain retrieves the chain support for a chain if it exists. 266 func (r *Registrar) GetChain(chainID string) *ChainSupport { 267 r.lock.RLock() 268 defer r.lock.RUnlock() 269 270 return r.chains[chainID] 271 } 272 273 func (r *Registrar) newLedgerResources(configTx *cb.Envelope) *ledgerResources { 274 payload, err := protoutil.UnmarshalPayload(configTx.Payload) 275 if err != nil { 276 logger.Panicf("Error umarshaling envelope to payload: %s", err) 277 } 278 279 if payload.Header == nil { 280 logger.Panicf("Missing channel header: %s", err) 281 } 282 283 chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader) 284 if err != nil { 285 logger.Panicf("Error unmarshaling channel header: %s", err) 286 } 287 288 configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data) 289 if err != nil { 290 logger.Panicf("Error umarshaling config envelope from payload data: %s", err) 291 } 292 293 bundle, err := channelconfig.NewBundle(chdr.ChannelId, configEnvelope.Config, r.bccsp) 294 if err != nil { 295 logger.Panicf("Error creating channelconfig bundle: %s", err) 296 } 297 298 checkResourcesOrPanic(bundle) 299 300 ledger, err := r.ledgerFactory.GetOrCreate(chdr.ChannelId) 301 if err != nil { 302 logger.Panicf("Error getting ledger for %s", chdr.ChannelId) 303 } 304 305 return &ledgerResources{ 306 configResources: &configResources{ 307 mutableResources: channelconfig.NewBundleSource(bundle, r.callbacks...), 308 bccsp: r.bccsp, 309 }, 310 ReadWriter: ledger, 311 } 312 } 313 314 // CreateChain makes the Registrar create a chain with the given name. 315 func (r *Registrar) CreateChain(chainName string) { 316 lf, err := r.ledgerFactory.GetOrCreate(chainName) 317 if err != nil { 318 logger.Panicf("Failed obtaining ledger factory for %s: %v", chainName, err) 319 } 320 chain := r.GetChain(chainName) 321 if chain != nil { 322 logger.Infof("A chain of type %T for channel %s already exists. "+ 323 "Halting it.", chain.Chain, chainName) 324 chain.Halt() 325 } 326 r.newChain(configTx(lf)) 327 } 328 329 func (r *Registrar) newChain(configtx *cb.Envelope) { 330 r.lock.Lock() 331 defer r.lock.Unlock() 332 333 ledgerResources := r.newLedgerResources(configtx) 334 // If we have no blocks, we need to create the genesis block ourselves. 335 if ledgerResources.Height() == 0 { 336 ledgerResources.Append(blockledger.CreateNextBlock(ledgerResources, []*cb.Envelope{configtx})) 337 } 338 339 // Copy the map to allow concurrent reads from broadcast/deliver while the new chainSupport is 340 newChains := make(map[string]*ChainSupport) 341 for key, value := range r.chains { 342 newChains[key] = value 343 } 344 345 cs := newChainSupport(r, ledgerResources, r.consenters, r.signer, r.blockcutterMetrics, r.bccsp) 346 chainID := ledgerResources.ConfigtxValidator().ChannelID() 347 348 logger.Infof("Created and starting new channel %s", chainID) 349 350 newChains[string(chainID)] = cs 351 cs.start() 352 353 r.chains = newChains 354 } 355 356 // ChannelsCount returns the count of the current total number of channels. 357 func (r *Registrar) ChannelsCount() int { 358 r.lock.RLock() 359 defer r.lock.RUnlock() 360 361 return len(r.chains) 362 } 363 364 // NewChannelConfig produces a new template channel configuration based on the system channel's current config. 365 func (r *Registrar) NewChannelConfig(envConfigUpdate *cb.Envelope) (channelconfig.Resources, error) { 366 return r.templator.NewChannelConfig(envConfigUpdate) 367 } 368 369 // CreateBundle calls channelconfig.NewBundle 370 func (r *Registrar) CreateBundle(channelID string, config *cb.Config) (channelconfig.Resources, error) { 371 return channelconfig.NewBundle(channelID, config, r.bccsp) 372 }