github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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 "reflect" 22 23 "github.com/hyperledger/fabric/common/config" 24 "github.com/hyperledger/fabric/common/configtx" 25 configtxapi "github.com/hyperledger/fabric/common/configtx/api" 26 "github.com/hyperledger/fabric/orderer/common/filter" 27 cb "github.com/hyperledger/fabric/protos/common" 28 "github.com/hyperledger/fabric/protos/utils" 29 30 "github.com/golang/protobuf/proto" 31 ) 32 33 // Define some internal interfaces for easier mocking 34 type chainCreator interface { 35 NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxapi.Manager, error) 36 newChain(configTx *cb.Envelope) 37 channelsCount() int 38 } 39 40 type limitedSupport interface { 41 SharedConfig() config.Orderer 42 } 43 44 type systemChainCommitter struct { 45 filter *systemChainFilter 46 configTx *cb.Envelope 47 } 48 49 func (scc *systemChainCommitter) Isolated() bool { 50 return true 51 } 52 53 func (scc *systemChainCommitter) Commit() { 54 scc.filter.cc.newChain(scc.configTx) 55 } 56 57 type systemChainFilter struct { 58 cc chainCreator 59 support limitedSupport 60 } 61 62 func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule { 63 return &systemChainFilter{ 64 support: ls, 65 cc: cc, 66 } 67 } 68 69 func (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, filter.Committer) { 70 msgData := &cb.Payload{} 71 72 err := proto.Unmarshal(env.Payload, msgData) 73 if err != nil { 74 return filter.Forward, nil 75 } 76 77 if msgData.Header == nil { 78 return filter.Forward, nil 79 } 80 81 chdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader) 82 if err != nil { 83 return filter.Forward, nil 84 } 85 86 if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION) { 87 return filter.Forward, nil 88 } 89 90 maxChannels := scf.support.SharedConfig().MaxChannelsCount() 91 if maxChannels > 0 { 92 // We check for strictly greater than to accommodate the system channel 93 if uint64(scf.cc.channelsCount()) > maxChannels { 94 logger.Warningf("Rejecting channel creation because the orderer has reached the maximum number of channels, %d", maxChannels) 95 return filter.Reject, nil 96 } 97 } 98 99 configTx := &cb.Envelope{} 100 err = proto.Unmarshal(msgData.Data, configTx) 101 if err != nil { 102 return filter.Reject, nil 103 } 104 105 err = scf.authorizeAndInspect(configTx) 106 if err != nil { 107 logger.Debugf("Rejecting channel creation because: %s", err) 108 return filter.Reject, nil 109 } 110 111 return filter.Accept, &systemChainCommitter{ 112 filter: scf, 113 configTx: configTx, 114 } 115 } 116 117 func (scf *systemChainFilter) authorize(configEnvelope *cb.ConfigEnvelope) (configtxapi.Manager, error) { 118 if configEnvelope.LastUpdate == nil { 119 return nil, fmt.Errorf("Must include a config update") 120 } 121 122 configManager, err := scf.cc.NewChannelConfig(configEnvelope.LastUpdate) 123 if err != nil { 124 return nil, fmt.Errorf("Error constructing new channel config from update: %s", err) 125 } 126 127 newChannelConfigEnv, err := configManager.ProposeConfigUpdate(configEnvelope.LastUpdate) 128 if err != nil { 129 return nil, err 130 } 131 132 err = configManager.Apply(newChannelConfigEnv) 133 if err != nil { 134 return nil, err 135 } 136 137 return configManager, nil 138 } 139 140 func (scf *systemChainFilter) inspect(proposedManager, configManager configtxapi.Manager) error { 141 proposedEnv := proposedManager.ConfigEnvelope() 142 actualEnv := configManager.ConfigEnvelope() 143 if !reflect.DeepEqual(proposedEnv.Config, actualEnv.Config) { 144 return fmt.Errorf("The 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 }