github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/configupdate/configupdate.go (about) 1 /* 2 Copyright IBM Corp. 2017 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 // configupdate is an implementation of the broadcast.Proccessor interface 18 // It facilitates the preprocessing of CONFIG_UPDATE transactions which can 19 // generate either new CONFIG transactions or new channel creation 20 // ORDERER_TRANSACTION messages. 21 package configupdate 22 23 import ( 24 "fmt" 25 26 "github.com/hyperledger/fabric/common/configtx" 27 "github.com/hyperledger/fabric/common/crypto" 28 cb "github.com/hyperledger/fabric/protos/common" 29 "github.com/hyperledger/fabric/protos/utils" 30 31 "github.com/op/go-logging" 32 ) 33 34 var logger = logging.MustGetLogger("orderer/multichain") 35 36 const ( 37 // These should eventually be derived from the channel support once enabled 38 msgVersion = int32(0) 39 epoch = 0 40 ) 41 42 // SupportManager provides a way for the Handler to look up the Support for a chain 43 type SupportManager interface { 44 // GetChain gets the chain support for a given ChannelId 45 GetChain(chainID string) (Support, bool) 46 } 47 48 // Support enumerates a subset of the full channel support function which is required for this package 49 type Support interface { 50 // ProposeConfigUpdate applies a CONFIG_UPDATE to an existing config to produce a *cb.ConfigEnvelope 51 ProposeConfigUpdate(env *cb.Envelope) (*cb.ConfigEnvelope, error) 52 } 53 54 type Processor struct { 55 signer crypto.LocalSigner 56 manager SupportManager 57 systemChannelID string 58 } 59 60 func New(systemChannelID string, supportManager SupportManager, signer crypto.LocalSigner) *Processor { 61 return &Processor{ 62 systemChannelID: systemChannelID, 63 manager: supportManager, 64 signer: signer, 65 } 66 } 67 68 func channelID(env *cb.Envelope) (string, error) { 69 envPayload, err := utils.UnmarshalPayload(env.Payload) 70 if err != nil { 71 return "", fmt.Errorf("Failing to process config update because of payload unmarshaling error: %s", err) 72 } 73 74 if envPayload.Header == nil /* || envPayload.Header.ChannelHeader == nil */ { 75 return "", fmt.Errorf("Failing to process config update because no channel ID was set") 76 } 77 78 chdr, err := utils.UnmarshalChannelHeader(envPayload.Header.ChannelHeader) 79 if err != nil { 80 return "", fmt.Errorf("Failing to process config update because of channel header unmarshaling error: %s", err) 81 } 82 83 if chdr.ChannelId == "" { 84 return "", fmt.Errorf("Failing to process config update because no channel ID was set") 85 } 86 87 return chdr.ChannelId, nil 88 } 89 90 // Process takes in an envelope of type CONFIG_UPDATE and proceses it 91 // to transform it either into to a new channel creation request, or 92 // into a channel CONFIG transaction (or errors on failure) 93 func (p *Processor) Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) { 94 channelID, err := channelID(envConfigUpdate) 95 if err != nil { 96 return nil, err 97 } 98 99 support, ok := p.manager.GetChain(channelID) 100 if ok { 101 logger.Debugf("Processing channel reconfiguration request for channel %s", channelID) 102 return p.existingChannelConfig(envConfigUpdate, channelID, support) 103 } 104 105 logger.Debugf("Processing channel creation request for channel %s", channelID) 106 return p.newChannelConfig(channelID, envConfigUpdate) 107 } 108 109 func (p *Processor) existingChannelConfig(envConfigUpdate *cb.Envelope, channelID string, support Support) (*cb.Envelope, error) { 110 configEnvelope, err := support.ProposeConfigUpdate(envConfigUpdate) 111 if err != nil { 112 return nil, err 113 } 114 115 return utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID, p.signer, configEnvelope, msgVersion, epoch) 116 } 117 118 func createInitialConfig(envConfigUpdate *cb.Envelope) (*cb.ConfigEnvelope, error) { 119 // TODO, for now, this assumes the update contains the entire initial config 120 // in the future, a subset of config needs to be allowed 121 122 configUpdatePayload, err := utils.UnmarshalPayload(envConfigUpdate.Payload) 123 if err != nil { 124 return nil, fmt.Errorf("Failing initial channel config creation because of payload unmarshaling error: %s", err) 125 } 126 127 configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(configUpdatePayload.Data) 128 if err != nil { 129 return nil, fmt.Errorf("Failing initial channel config creation because of config update envelope unmarshaling error: %s", err) 130 } 131 132 configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate) 133 if err != nil { 134 return nil, fmt.Errorf("Failing initial channel config creation because of config update unmarshaling error: %s", err) 135 } 136 137 return &cb.ConfigEnvelope{ 138 Config: &cb.Config{ 139 Header: configUpdate.Header, 140 Channel: configUpdate.WriteSet, 141 }, 142 143 LastUpdate: envConfigUpdate, 144 }, nil 145 } 146 147 func (p *Processor) newChannelConfig(channelID string, envConfigUpdate *cb.Envelope) (*cb.Envelope, error) { 148 initialConfig, err := createInitialConfig(envConfigUpdate) 149 if err != nil { 150 return nil, err 151 } 152 153 envConfig, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID, p.signer, initialConfig, msgVersion, epoch) 154 if err != nil { 155 return nil, err 156 } 157 158 return utils.CreateSignedEnvelope(cb.HeaderType_ORDERER_TRANSACTION, p.systemChannelID, p.signer, envConfig, msgVersion, epoch) 159 }