github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/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/config"
    23  	"github.com/hyperledger/fabric/common/configtx"
    24  	configtxapi "github.com/hyperledger/fabric/common/configtx/api"
    25  	"github.com/hyperledger/fabric/orderer/common/filter"
    26  	cb "github.com/hyperledger/fabric/protos/common"
    27  	"github.com/hyperledger/fabric/protos/utils"
    28  
    29  	"github.com/golang/protobuf/proto"
    30  )
    31  
    32  // Define some internal interfaces for easier mocking
    33  type chainCreator interface {
    34  	NewChannelConfig(envConfigUpdate *cb.Envelope) (configtxapi.Manager, error)
    35  	newChain(configTx *cb.Envelope)
    36  	channelsCount() int
    37  }
    38  
    39  type limitedSupport interface {
    40  	SharedConfig() config.Orderer
    41  }
    42  
    43  type systemChainCommitter struct {
    44  	filter   *systemChainFilter
    45  	configTx *cb.Envelope
    46  }
    47  
    48  func (scc *systemChainCommitter) Isolated() bool {
    49  	return true
    50  }
    51  
    52  func (scc *systemChainCommitter) Commit() {
    53  	scc.filter.cc.newChain(scc.configTx)
    54  }
    55  
    56  type systemChainFilter struct {
    57  	cc      chainCreator
    58  	support limitedSupport
    59  }
    60  
    61  func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule {
    62  	return &systemChainFilter{
    63  		support: ls,
    64  		cc:      cc,
    65  	}
    66  }
    67  
    68  func (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, filter.Committer) {
    69  	msgData := &cb.Payload{}
    70  
    71  	err := proto.Unmarshal(env.Payload, msgData)
    72  	if err != nil {
    73  		return filter.Forward, nil
    74  	}
    75  
    76  	if msgData.Header == nil {
    77  		return filter.Forward, nil
    78  	}
    79  
    80  	chdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader)
    81  	if err != nil {
    82  		return filter.Forward, nil
    83  	}
    84  
    85  	if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION) {
    86  		return filter.Forward, nil
    87  	}
    88  
    89  	maxChannels := scf.support.SharedConfig().MaxChannelsCount()
    90  	if maxChannels > 0 {
    91  		// We check for strictly greater than to accommodate the system channel
    92  		if uint64(scf.cc.channelsCount()) > maxChannels {
    93  			logger.Warningf("Rejecting channel creation because the orderer has reached the maximum number of channels, %d", maxChannels)
    94  			return filter.Reject, nil
    95  		}
    96  	}
    97  
    98  	configTx := &cb.Envelope{}
    99  	err = proto.Unmarshal(msgData.Data, configTx)
   100  	if err != nil {
   101  		return filter.Reject, nil
   102  	}
   103  
   104  	err = scf.authorizeAndInspect(configTx)
   105  	if err != nil {
   106  		logger.Debugf("Rejecting channel creation because: %s", err)
   107  		return filter.Reject, nil
   108  	}
   109  
   110  	return filter.Accept, &systemChainCommitter{
   111  		filter:   scf,
   112  		configTx: configTx,
   113  	}
   114  }
   115  
   116  func (scf *systemChainFilter) authorize(configEnvelope *cb.ConfigEnvelope) (configtxapi.Manager, error) {
   117  	if configEnvelope.LastUpdate == nil {
   118  		return nil, fmt.Errorf("Must include a config update")
   119  	}
   120  
   121  	configManager, err := scf.cc.NewChannelConfig(configEnvelope.LastUpdate)
   122  	if err != nil {
   123  		return nil, fmt.Errorf("Error constructing new channel config from update: %s", err)
   124  	}
   125  
   126  	newChannelConfigEnv, err := configManager.ProposeConfigUpdate(configEnvelope.LastUpdate)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  
   131  	err = configManager.Apply(newChannelConfigEnv)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  
   136  	return configManager, nil
   137  }
   138  
   139  func (scf *systemChainFilter) inspect(proposedManager, configManager configtxapi.Manager) error {
   140  	proposedEnv := proposedManager.ConfigEnvelope()
   141  	actualEnv := configManager.ConfigEnvelope()
   142  	// reflect.DeepEqual will not work here, because it considers nil and empty maps as unequal
   143  	if !proto.Equal(proposedEnv.Config, actualEnv.Config) {
   144  		return fmt.Errorf("config proposed by the channel creation request did not match the config received with the channel creation request")
   145  	}
   146  	return nil
   147  }
   148  
   149  func (scf *systemChainFilter) authorizeAndInspect(configTx *cb.Envelope) error {
   150  	payload := &cb.Payload{}
   151  	err := proto.Unmarshal(configTx.Payload, payload)
   152  	if err != nil {
   153  		return fmt.Errorf("Rejecting chain proposal: Error unmarshaling envelope payload: %s", err)
   154  	}
   155  
   156  	if payload.Header == nil {
   157  		return fmt.Errorf("Rejecting chain proposal: Not a config transaction")
   158  	}
   159  
   160  	chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   161  	if err != nil {
   162  		return fmt.Errorf("Rejecting chain proposal: Error unmarshaling channel header: %s", err)
   163  	}
   164  
   165  	if chdr.Type != int32(cb.HeaderType_CONFIG) {
   166  		return fmt.Errorf("Rejecting chain proposal: Not a config transaction")
   167  	}
   168  
   169  	configEnvelope := &cb.ConfigEnvelope{}
   170  	err = proto.Unmarshal(payload.Data, configEnvelope)
   171  	if err != nil {
   172  		return fmt.Errorf("Rejecting chain proposal: Error unmarshalling config envelope from payload: %s", err)
   173  	}
   174  
   175  	// Make sure that the config was signed by the appropriate authorized entities
   176  	proposedManager, err := scf.authorize(configEnvelope)
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	initializer := configtx.NewInitializer()
   182  	configManager, err := configtx.NewManagerImpl(configTx, initializer, nil)
   183  	if err != nil {
   184  		return fmt.Errorf("Failed to create config manager and handlers: %s", err)
   185  	}
   186  
   187  	// Make sure that the config does not modify any of the orderer
   188  	return scf.inspect(proposedManager, configManager)
   189  }