github.com/true-sqn/fabric@v2.1.1+incompatible/core/peer/channel.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package peer 8 9 import ( 10 "sync" 11 12 "github.com/hyperledger/fabric-protos-go/common" 13 "github.com/hyperledger/fabric/bccsp" 14 "github.com/hyperledger/fabric/common/channelconfig" 15 "github.com/hyperledger/fabric/common/ledger/blockledger" 16 "github.com/hyperledger/fabric/common/ledger/blockledger/fileledger" 17 "github.com/hyperledger/fabric/common/policies" 18 "github.com/hyperledger/fabric/core/ledger" 19 "github.com/hyperledger/fabric/core/transientstore" 20 "github.com/hyperledger/fabric/msp" 21 ) 22 23 // Channel manages objects and configuration associated with a Channel. 24 type Channel struct { 25 ledger ledger.PeerLedger 26 store *transientstore.Store 27 cryptoProvider bccsp.BCCSP 28 29 // applyLock is used to serialize calls to Apply and bundle update processing. 30 applyLock sync.Mutex 31 // bundleSource is used to validate and apply channel configuration updates. 32 // This should not be used for retrieving resources. 33 bundleSource *channelconfig.BundleSource 34 35 // lock is used to serialize access to resources 36 lock sync.RWMutex 37 // resources is used to acquire configuration bundle resources. The reference 38 // is maintained by callbacks from the bundleSource. 39 resources channelconfig.Resources 40 } 41 42 // Apply is used to validate and apply configuration transactions for a channel. 43 func (c *Channel) Apply(configtx *common.ConfigEnvelope) error { 44 c.applyLock.Lock() 45 defer c.applyLock.Unlock() 46 47 configTxValidator := c.Resources().ConfigtxValidator() 48 err := configTxValidator.Validate(configtx) 49 if err != nil { 50 return err 51 } 52 53 bundle, err := channelconfig.NewBundle(configTxValidator.ChannelID(), configtx.Config, c.cryptoProvider) 54 if err != nil { 55 return err 56 } 57 58 channelconfig.LogSanityChecks(bundle) 59 err = c.bundleSource.ValidateNew(bundle) 60 if err != nil { 61 return err 62 } 63 64 capabilitiesSupportedOrPanic(bundle) 65 66 c.bundleSource.Update(bundle) 67 return nil 68 } 69 70 // bundleUpdate is called by the bundleSource when the channel configuration 71 // changes. 72 func (c *Channel) bundleUpdate(b *channelconfig.Bundle) { 73 c.lock.Lock() 74 c.resources = b 75 c.lock.Unlock() 76 } 77 78 // Resources returns the active channel configuration bundle. 79 func (c *Channel) Resources() channelconfig.Resources { 80 c.lock.RLock() 81 res := c.resources 82 c.lock.RUnlock() 83 return res 84 } 85 86 // Sequence returns the current config sequence number of the channel. 87 func (c *Channel) Sequence() uint64 { 88 return c.Resources().ConfigtxValidator().Sequence() 89 } 90 91 // PolicyManager returns the policies.Manager for the channel that reflects the 92 // current channel configuration. Users should not memoize references to this object. 93 func (c *Channel) PolicyManager() policies.Manager { 94 return c.Resources().PolicyManager() 95 } 96 97 // Capabilities gets the application capabilities for the current channel 98 // configuration. 99 func (c *Channel) Capabilities() channelconfig.ApplicationCapabilities { 100 ac, ok := c.Resources().ApplicationConfig() 101 if !ok { 102 return nil 103 } 104 return ac.Capabilities() 105 } 106 107 // GetMSPIDs retrieves the MSP IDs of the organziations in the current channel 108 // configuration. 109 func (c *Channel) GetMSPIDs() []string { 110 ac, ok := c.Resources().ApplicationConfig() 111 if !ok || ac.Organizations() == nil { 112 return nil 113 } 114 115 var mspIDs []string 116 for _, org := range ac.Organizations() { 117 mspIDs = append(mspIDs, org.MSPID()) 118 } 119 120 return mspIDs 121 } 122 123 // MSPManager returns the msp.MSPManager that reflects the current channel 124 // configuration. Users should not memoize references to this object. 125 func (c *Channel) MSPManager() msp.MSPManager { 126 return c.Resources().MSPManager() 127 } 128 129 // Ledger returns the ledger associated with this channel. 130 func (c *Channel) Ledger() ledger.PeerLedger { 131 return c.ledger 132 } 133 134 // Store returns the transient store associated with this channel. 135 func (c *Channel) Store() *transientstore.Store { 136 return c.store 137 } 138 139 // Reader returns a blockledger.Reader backed by the ledger associated with 140 // this channel. 141 func (c *Channel) Reader() blockledger.Reader { 142 return fileledger.NewFileLedger(fileLedgerBlockStore{c.ledger}) 143 } 144 145 // Errored returns a channel that can be used to determine if a backing 146 // resource has errored. At this point in time, the peer does not have any 147 // error conditions that lead to this function signaling that an error has 148 // occurred. 149 func (c *Channel) Errored() <-chan struct{} { 150 // If this is ever updated to return a real channel, the error message 151 // in deliver.go around this channel closing should be updated. 152 return nil 153 } 154 155 func capabilitiesSupportedOrPanic(res channelconfig.Resources) { 156 ac, ok := res.ApplicationConfig() 157 if !ok { 158 peerLogger.Panicf("[channel %s] does not have application config so is incompatible", res.ConfigtxValidator().ChannelID()) 159 } 160 161 if err := ac.Capabilities().Supported(); err != nil { 162 peerLogger.Panicf("[channel %s] incompatible: %s", res.ConfigtxValidator().ChannelID(), err) 163 } 164 165 if err := res.ChannelConfig().Capabilities().Supported(); err != nil { 166 peerLogger.Panicf("[channel %s] incompatible: %s", res.ConfigtxValidator().ChannelID(), err) 167 } 168 }