github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/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 configtxapi "github.com/hyperledger/fabric/common/configtx/api" 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/configupdate") 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 // NewChannelConfig returns a bare bones configuration ready for channel 48 // creation request to be applied on top of it 49 NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxapi.Manager, error) 50 } 51 52 // Support enumerates a subset of the full channel support function which is required for this package 53 type Support interface { 54 // ProposeConfigUpdate applies a CONFIG_UPDATE to an existing config to produce a *cb.ConfigEnvelope 55 ProposeConfigUpdate(env *cb.Envelope) (*cb.ConfigEnvelope, error) 56 } 57 58 type Processor struct { 59 signer crypto.LocalSigner 60 manager SupportManager 61 systemChannelID string 62 systemChannelSupport Support 63 } 64 65 func New(systemChannelID string, supportManager SupportManager, signer crypto.LocalSigner) *Processor { 66 support, ok := supportManager.GetChain(systemChannelID) 67 if !ok { 68 logger.Panicf("Supplied a SupportManager which did not contain a system channel") 69 } 70 71 return &Processor{ 72 systemChannelID: systemChannelID, 73 manager: supportManager, 74 signer: signer, 75 systemChannelSupport: support, 76 } 77 } 78 79 func channelID(env *cb.Envelope) (string, error) { 80 envPayload, err := utils.UnmarshalPayload(env.Payload) 81 if err != nil { 82 return "", fmt.Errorf("Failing to process config update because of payload unmarshaling error: %s", err) 83 } 84 85 if envPayload.Header == nil /* || envPayload.Header.ChannelHeader == nil */ { 86 return "", fmt.Errorf("Failing to process config update because no channel ID was set") 87 } 88 89 chdr, err := utils.UnmarshalChannelHeader(envPayload.Header.ChannelHeader) 90 if err != nil { 91 return "", fmt.Errorf("Failing to process config update because of channel header unmarshaling error: %s", err) 92 } 93 94 if chdr.ChannelId == "" { 95 return "", fmt.Errorf("Failing to process config update because no channel ID was set") 96 } 97 98 return chdr.ChannelId, nil 99 } 100 101 // Process takes in an envelope of type CONFIG_UPDATE and proceses it 102 // to transform it either into to a new channel creation request, or 103 // into a channel CONFIG transaction (or errors on failure) 104 func (p *Processor) Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) { 105 channelID, err := channelID(envConfigUpdate) 106 if err != nil { 107 return nil, err 108 } 109 110 support, ok := p.manager.GetChain(channelID) 111 if ok { 112 logger.Debugf("Processing channel reconfiguration request for channel %s", channelID) 113 return p.existingChannelConfig(envConfigUpdate, channelID, support) 114 } 115 116 logger.Debugf("Processing channel creation request for channel %s", channelID) 117 return p.newChannelConfig(channelID, envConfigUpdate) 118 } 119 120 func (p *Processor) existingChannelConfig(envConfigUpdate *cb.Envelope, channelID string, support Support) (*cb.Envelope, error) { 121 configEnvelope, err := support.ProposeConfigUpdate(envConfigUpdate) 122 if err != nil { 123 return nil, err 124 } 125 126 return utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID, p.signer, configEnvelope, msgVersion, epoch) 127 } 128 129 func (p *Processor) proposeNewChannelToSystemChannel(newChannelEnvConfig *cb.Envelope) (*cb.Envelope, error) { 130 return utils.CreateSignedEnvelope(cb.HeaderType_ORDERER_TRANSACTION, p.systemChannelID, p.signer, newChannelEnvConfig, msgVersion, epoch) 131 } 132 133 func (p *Processor) newChannelConfig(channelID string, envConfigUpdate *cb.Envelope) (*cb.Envelope, error) { 134 ctxm, err := p.manager.NewChannelConfig(envConfigUpdate) 135 if err != nil { 136 return nil, err 137 } 138 139 newChannelConfigEnv, err := ctxm.ProposeConfigUpdate(envConfigUpdate) 140 if err != nil { 141 return nil, err 142 } 143 144 newChannelEnvConfig, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID, p.signer, newChannelConfigEnv, msgVersion, epoch) 145 if err != nil { 146 return nil, err 147 } 148 149 return p.proposeNewChannelToSystemChannel(newChannelEnvConfig) 150 }