github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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/configtx" 23 configvaluesapi "github.com/hyperledger/fabric/common/configvalues" 24 configtxorderer "github.com/hyperledger/fabric/common/configvalues/channel/orderer" 25 "github.com/hyperledger/fabric/common/policies" 26 "github.com/hyperledger/fabric/orderer/common/filter" 27 cb "github.com/hyperledger/fabric/protos/common" 28 ab "github.com/hyperledger/fabric/protos/orderer" 29 "github.com/hyperledger/fabric/protos/utils" 30 31 "github.com/golang/protobuf/proto" 32 ) 33 34 // Define some internal interfaces for easier mocking 35 type chainCreator interface { 36 newChain(configTx *cb.Envelope) 37 } 38 39 type limitedSupport interface { 40 PolicyManager() policies.Manager 41 SharedConfig() configvaluesapi.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 /* || msgData.Header.ChannelHeader == 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 configTx := &cb.Envelope{} 91 err = proto.Unmarshal(msgData.Data, configTx) 92 if err != nil { 93 return filter.Reject, nil 94 } 95 96 err = scf.authorizeAndInspect(configTx) 97 if err != nil { 98 logger.Debugf("Rejecting channel creation because: %s", err) 99 return filter.Reject, nil 100 } 101 102 return filter.Accept, &systemChainCommitter{ 103 filter: scf, 104 configTx: configTx, 105 } 106 } 107 108 func (scf *systemChainFilter) authorize(configEnvelope *cb.ConfigEnvelope) error { 109 if configEnvelope.LastUpdate == nil { 110 return fmt.Errorf("Must include a config update") 111 } 112 113 configEnvEnvPayload, err := utils.UnmarshalPayload(configEnvelope.LastUpdate.Payload) 114 if err != nil { 115 return fmt.Errorf("Failing to validate chain creation because of payload unmarshaling error: %s", err) 116 } 117 118 configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(configEnvEnvPayload.Data) 119 if err != nil { 120 return fmt.Errorf("Failing to validate chain creation because of config update envelope unmarshaling error: %s", err) 121 } 122 123 config, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate) 124 if err != nil { 125 return fmt.Errorf("Failing to validate chain creation because of unmarshaling error: %s", err) 126 } 127 128 if config.WriteSet == nil { 129 return fmt.Errorf("Failing to validate channel creation because WriteSet is nil") 130 } 131 132 ordererGroup, ok := config.WriteSet.Groups[configtxorderer.GroupKey] 133 if !ok { 134 return fmt.Errorf("Rejecting channel creation because it is missing orderer group") 135 } 136 137 creationConfigItem, ok := ordererGroup.Values[configtx.CreationPolicyKey] 138 if !ok { 139 return fmt.Errorf("Failing to validate chain creation because no creation policy included") 140 } 141 142 creationPolicy := &ab.CreationPolicy{} 143 err = proto.Unmarshal(creationConfigItem.Value, creationPolicy) 144 if err != nil { 145 return fmt.Errorf("Failing to validate chain creation because first config item could not unmarshal to a CreationPolicy: %s", err) 146 } 147 148 ok = false 149 for _, chainCreatorPolicy := range scf.support.SharedConfig().ChainCreationPolicyNames() { 150 if chainCreatorPolicy == creationPolicy.Policy { 151 ok = true 152 break 153 } 154 } 155 156 if !ok { 157 return fmt.Errorf("Failed to validate chain creation because chain creation policy (%s) is not authorized for chain creation", creationPolicy.Policy) 158 } 159 160 policy, ok := scf.support.PolicyManager().GetPolicy(creationPolicy.Policy) 161 if !ok { 162 return fmt.Errorf("Failed to get policy for chain creation despite it being listed as an authorized policy") 163 } 164 165 signedData, err := configUpdateEnv.AsSignedData() 166 if err != nil { 167 return fmt.Errorf("Failed to validate chain creation because config envelope could not be converted to signed data: %s", err) 168 } 169 170 err = policy.Evaluate(signedData) 171 if err != nil { 172 return fmt.Errorf("Failed to validate chain creation, did not satisfy policy: %s", err) 173 } 174 175 return nil 176 } 177 178 func (scf *systemChainFilter) inspect(configResources *configResources) error { 179 // XXX decide what it is that we will require to be the same in the new config, and what will be allowed to be different 180 // Are all keys allowed? etc. 181 182 return nil 183 } 184 185 func (scf *systemChainFilter) authorizeAndInspect(configTx *cb.Envelope) error { 186 payload := &cb.Payload{} 187 err := proto.Unmarshal(configTx.Payload, payload) 188 if err != nil { 189 return fmt.Errorf("Rejecting chain proposal: Error unmarshaling envelope payload: %s", err) 190 } 191 192 if payload.Header == nil /* || payload.Header.ChannelHeader == nil */ { 193 return fmt.Errorf("Rejecting chain proposal: Not a config transaction") 194 } 195 196 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 197 if err != nil { 198 return fmt.Errorf("Rejecting chain proposal: Error unmarshaling channel header: %s", err) 199 } 200 201 if chdr.Type != int32(cb.HeaderType_CONFIG) { 202 return fmt.Errorf("Rejecting chain proposal: Not a config transaction") 203 } 204 205 configEnvelope := &cb.ConfigEnvelope{} 206 err = proto.Unmarshal(payload.Data, configEnvelope) 207 if err != nil { 208 return fmt.Errorf("Rejecting chain proposal: Error unmarshalling config envelope from payload: %s", err) 209 } 210 211 // Make sure that the config was signed by the appropriate authorized entities 212 err = scf.authorize(configEnvelope) 213 if err != nil { 214 return err 215 } 216 217 configResources, err := newConfigResources(configEnvelope) 218 if err != nil { 219 return fmt.Errorf("Failed to create config manager and handlers: %s", err) 220 } 221 222 // Make sure that the config does not modify any of the orderer 223 return scf.inspect(configResources) 224 }