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  }