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  }