github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/orderer/multichain/systemchain.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package multichain 18 19 import ( 20 "fmt" 21 22 "github.com/hyperledger/fabric/common/config" 23 "github.com/hyperledger/fabric/common/configtx" 24 configtxapi "github.com/hyperledger/fabric/common/configtx/api" 25 "github.com/hyperledger/fabric/orderer/common/filter" 26 cb "github.com/hyperledger/fabric/protos/common" 27 "github.com/hyperledger/fabric/protos/utils" 28 29 "github.com/golang/protobuf/proto" 30 ) 31 32 // Define some internal interfaces for easier mocking 33 type chainCreator interface { 34 NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxapi.Manager, error) 35 newChain(configTx *cb.Envelope) 36 channelsCount() int 37 } 38 39 type limitedSupport interface { 40 SharedConfig() config.Orderer 41 } 42 43 type systemChainCommitter struct { 44 filter *systemChainFilter 45 configTx *cb.Envelope 46 } 47 48 func (scc *systemChainCommitter) Isolated() bool { 49 return true 50 } 51 52 func (scc *systemChainCommitter) Commit() { 53 scc.filter.cc.newChain(scc.configTx) 54 } 55 56 type systemChainFilter struct { 57 cc chainCreator 58 support limitedSupport 59 } 60 61 func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule { 62 return &systemChainFilter{ 63 support: ls, 64 cc: cc, 65 } 66 } 67 68 func (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, filter.Committer) { 69 msgData := &cb.Payload{} 70 71 err := proto.Unmarshal(env.Payload, msgData) 72 if err != nil { 73 return filter.Forward, nil 74 } 75 76 if msgData.Header == nil { 77 return filter.Forward, nil 78 } 79 80 chdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader) 81 if err != nil { 82 return filter.Forward, nil 83 } 84 85 if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION) { 86 return filter.Forward, nil 87 } 88 89 maxChannels := scf.support.SharedConfig().MaxChannelsCount() 90 if maxChannels > 0 { 91 // We check for strictly greater than to accommodate the system channel 92 if uint64(scf.cc.channelsCount()) > maxChannels { 93 logger.Warningf("Rejecting channel creation because the orderer has reached the maximum number of channels, %d", maxChannels) 94 return filter.Reject, nil 95 } 96 } 97 98 configTx := &cb.Envelope{} 99 err = proto.Unmarshal(msgData.Data, configTx) 100 if err != nil { 101 return filter.Reject, nil 102 } 103 104 err = scf.authorizeAndInspect(configTx) 105 if err != nil { 106 logger.Debugf("Rejecting channel creation because: %s", err) 107 return filter.Reject, nil 108 } 109 110 return filter.Accept, &systemChainCommitter{ 111 filter: scf, 112 configTx: configTx, 113 } 114 } 115 116 func (scf *systemChainFilter) authorize(configEnvelope *cb.ConfigEnvelope) (configtxapi.Manager, error) { 117 if configEnvelope.LastUpdate == nil { 118 return nil, fmt.Errorf("Must include a config update") 119 } 120 121 configManager, err := scf.cc.NewChannelConfig(configEnvelope.LastUpdate) 122 if err != nil { 123 return nil, fmt.Errorf("Error constructing new channel config from update: %s", err) 124 } 125 126 newChannelConfigEnv, err := configManager.ProposeConfigUpdate(configEnvelope.LastUpdate) 127 if err != nil { 128 return nil, err 129 } 130 131 err = configManager.Apply(newChannelConfigEnv) 132 if err != nil { 133 return nil, err 134 } 135 136 return configManager, nil 137 } 138 139 func (scf *systemChainFilter) inspect(proposedManager, configManager configtxapi.Manager) error { 140 proposedEnv := proposedManager.ConfigEnvelope() 141 actualEnv := configManager.ConfigEnvelope() 142 // reflect.DeepEqual will not work here, because it considers nil and empty maps as unequal 143 if !proto.Equal(proposedEnv.Config, actualEnv.Config) { 144 return fmt.Errorf("config proposed by the channel creation request did not match the config received with the channel creation request") 145 } 146 return nil 147 } 148 149 func (scf *systemChainFilter) authorizeAndInspect(configTx *cb.Envelope) error { 150 payload := &cb.Payload{} 151 err := proto.Unmarshal(configTx.Payload, payload) 152 if err != nil { 153 return fmt.Errorf("Rejecting chain proposal: Error unmarshaling envelope payload: %s", err) 154 } 155 156 if payload.Header == nil { 157 return fmt.Errorf("Rejecting chain proposal: Not a config transaction") 158 } 159 160 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 161 if err != nil { 162 return fmt.Errorf("Rejecting chain proposal: Error unmarshaling channel header: %s", err) 163 } 164 165 if chdr.Type != int32(cb.HeaderType_CONFIG) { 166 return fmt.Errorf("Rejecting chain proposal: Not a config transaction") 167 } 168 169 configEnvelope := &cb.ConfigEnvelope{} 170 err = proto.Unmarshal(payload.Data, configEnvelope) 171 if err != nil { 172 return fmt.Errorf("Rejecting chain proposal: Error unmarshalling config envelope from payload: %s", err) 173 } 174 175 // Make sure that the config was signed by the appropriate authorized entities 176 proposedManager, err := scf.authorize(configEnvelope) 177 if err != nil { 178 return err 179 } 180 181 initializer := configtx.NewInitializer() 182 configManager, err := configtx.NewManagerImpl(configTx, initializer, nil) 183 if err != nil { 184 return fmt.Errorf("Failed to create config manager and handlers: %s", err) 185 } 186 187 // Make sure that the config does not modify any of the orderer 188 return scf.inspect(proposedManager, configManager) 189 }