github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/msgprocessor/systemchannel.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package msgprocessor
     8  
     9  import (
    10  	"fmt"
    11  
    12  	"github.com/golang/protobuf/proto"
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	"github.com/hyperledger/fabric/bccsp"
    15  	"github.com/hyperledger/fabric/common/channelconfig"
    16  	"github.com/hyperledger/fabric/common/configtx"
    17  	"github.com/hyperledger/fabric/common/policies"
    18  	"github.com/hyperledger/fabric/internal/pkg/identity"
    19  	"github.com/hyperledger/fabric/orderer/common/localconfig"
    20  	"github.com/hyperledger/fabric/protoutil"
    21  	"github.com/pkg/errors"
    22  )
    23  
    24  // ChannelConfigTemplator can be used to generate config templates.
    25  type ChannelConfigTemplator interface {
    26  	// NewChannelConfig creates a new template configuration manager.
    27  	NewChannelConfig(env *cb.Envelope) (channelconfig.Resources, error)
    28  }
    29  
    30  // MetadataValidator can be used to validate updates to the consensus-specific metadata.
    31  type MetadataValidator interface {
    32  	ValidateConsensusMetadata(oldMetadata, newMetadata []byte, newChannel bool) error
    33  }
    34  
    35  // SystemChannel implements the Processor interface for the system channel.
    36  type SystemChannel struct {
    37  	*StandardChannel
    38  	templator ChannelConfigTemplator
    39  }
    40  
    41  // NewSystemChannel creates a new system channel message processor.
    42  func NewSystemChannel(support StandardChannelSupport, templator ChannelConfigTemplator, filters *RuleSet, bccsp bccsp.BCCSP) *SystemChannel {
    43  	logger.Debugf("Creating system channel msg processor for channel %s", support.ChannelID())
    44  	return &SystemChannel{
    45  		StandardChannel: NewStandardChannel(support, filters, bccsp),
    46  		templator:       templator,
    47  	}
    48  }
    49  
    50  // CreateSystemChannelFilters creates the set of filters for the ordering system chain.
    51  //
    52  // In maintenance mode, require the signature of /Channel/Orderer/Writers. This will filter out configuration
    53  // changes that are not related to consensus-type migration (e.g on /Channel/Application).
    54  func CreateSystemChannelFilters(
    55  	config localconfig.TopLevel,
    56  	chainCreator ChainCreator,
    57  	ledgerResources channelconfig.Resources,
    58  	validator MetadataValidator,
    59  ) *RuleSet {
    60  	rules := []Rule{
    61  		EmptyRejectRule,
    62  		NewSizeFilter(ledgerResources),
    63  		NewSigFilter(policies.ChannelWriters, policies.ChannelOrdererWriters, ledgerResources),
    64  		NewSystemChannelFilter(ledgerResources, chainCreator, validator),
    65  	}
    66  	if !config.General.Authentication.NoExpirationChecks {
    67  		expirationRule := NewExpirationRejectRule(ledgerResources)
    68  		// In case of DoS, expiration is inserted before SigFilter, so it is evaluated first
    69  		rules = append(rules[:2], append([]Rule{expirationRule}, rules[2:]...)...)
    70  	}
    71  	return NewRuleSet(rules)
    72  }
    73  
    74  // ProcessNormalMsg handles normal messages, rejecting them if they are not bound for the system channel ID
    75  // with ErrChannelDoesNotExist.
    76  func (s *SystemChannel) ProcessNormalMsg(msg *cb.Envelope) (configSeq uint64, err error) {
    77  	channelID, err := protoutil.ChannelID(msg)
    78  	if err != nil {
    79  		return 0, err
    80  	}
    81  
    82  	// For the StandardChannel message processing, we would not check the channel ID,
    83  	// because the message processor is looked up by channel ID.
    84  	// However, the system channel message processor is the catch all for messages
    85  	// which do not correspond to an extant channel, so we must check it here.
    86  	if channelID != s.support.ChannelID() {
    87  		return 0, ErrChannelDoesNotExist
    88  	}
    89  
    90  	return s.StandardChannel.ProcessNormalMsg(msg)
    91  }
    92  
    93  // ProcessConfigUpdateMsg handles messages of type CONFIG_UPDATE either for the system channel itself
    94  // or, for channel creation.  In the channel creation case, the CONFIG_UPDATE is wrapped into a resulting
    95  // ORDERER_TRANSACTION, and in the standard CONFIG_UPDATE case, a resulting CONFIG message
    96  func (s *SystemChannel) ProcessConfigUpdateMsg(envConfigUpdate *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) {
    97  	channelID, err := protoutil.ChannelID(envConfigUpdate)
    98  	if err != nil {
    99  		return nil, 0, err
   100  	}
   101  
   102  	logger.Debugf("Processing config update tx with system channel message processor for channel ID %s", channelID)
   103  
   104  	if channelID == s.support.ChannelID() {
   105  		return s.StandardChannel.ProcessConfigUpdateMsg(envConfigUpdate)
   106  	}
   107  
   108  	// XXX we should check that the signature on the outer envelope is at least valid for some MSP in the system channel
   109  
   110  	logger.Debugf("Processing channel create tx for channel %s on system channel %s", channelID, s.support.ChannelID())
   111  
   112  	// If the channel ID does not match the system channel, then this must be a channel creation transaction
   113  
   114  	bundle, err := s.templator.NewChannelConfig(envConfigUpdate)
   115  	if err != nil {
   116  		return nil, 0, err
   117  	}
   118  
   119  	newChannelConfigEnv, err := bundle.ConfigtxValidator().ProposeConfigUpdate(envConfigUpdate)
   120  	if err != nil {
   121  		return nil, 0, errors.WithMessagef(err, "error validating channel creation transaction for new channel '%s', could not successfully apply update to template configuration", channelID)
   122  	}
   123  
   124  	newChannelEnvConfig, err := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, channelID, s.support.Signer(), newChannelConfigEnv, msgVersion, epoch)
   125  	if err != nil {
   126  		return nil, 0, err
   127  	}
   128  
   129  	wrappedOrdererTransaction, err := protoutil.CreateSignedEnvelope(cb.HeaderType_ORDERER_TRANSACTION, s.support.ChannelID(), s.support.Signer(), newChannelEnvConfig, msgVersion, epoch)
   130  	if err != nil {
   131  		return nil, 0, err
   132  	}
   133  
   134  	// We re-apply the filters here, especially for the size filter, to ensure that the transaction we
   135  	// just constructed is not too large for our consenter.  It additionally reapplies the signature
   136  	// check, which although not strictly necessary, is a good sanity check, in case the orderer
   137  	// has not been configured with the right cert material.  The additional overhead of the signature
   138  	// check is negligible, as this is the channel creation path and not the normal path.
   139  	err = s.StandardChannel.filters.Apply(wrappedOrdererTransaction)
   140  	if err != nil {
   141  		return nil, 0, err
   142  	}
   143  
   144  	return wrappedOrdererTransaction, s.support.Sequence(), nil
   145  }
   146  
   147  // ProcessConfigMsg takes envelope of following two types:
   148  //   - `HeaderType_CONFIG`: system channel itself is the target of config, we simply unpack `ConfigUpdate`
   149  //     envelope from `LastUpdate` field and call `ProcessConfigUpdateMsg` on the underlying standard channel
   150  //   - `HeaderType_ORDERER_TRANSACTION`: it's a channel creation message, we unpack `ConfigUpdate` envelope
   151  //     and run `ProcessConfigUpdateMsg` on it
   152  func (s *SystemChannel) ProcessConfigMsg(env *cb.Envelope) (*cb.Envelope, uint64, error) {
   153  	payload, err := protoutil.UnmarshalPayload(env.Payload)
   154  	if err != nil {
   155  		return nil, 0, err
   156  	}
   157  
   158  	if payload.Header == nil {
   159  		return nil, 0, fmt.Errorf("Abort processing config msg because no head was set")
   160  	}
   161  
   162  	if payload.Header.ChannelHeader == nil {
   163  		return nil, 0, fmt.Errorf("Abort processing config msg because no channel header was set")
   164  	}
   165  
   166  	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   167  	if err != nil {
   168  		return nil, 0, fmt.Errorf("Abort processing config msg because channel header unmarshalling error: %s", err)
   169  	}
   170  
   171  	switch chdr.Type {
   172  	case int32(cb.HeaderType_CONFIG):
   173  		configEnvelope := &cb.ConfigEnvelope{}
   174  		if err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {
   175  			return nil, 0, err
   176  		}
   177  
   178  		return s.StandardChannel.ProcessConfigUpdateMsg(configEnvelope.LastUpdate)
   179  
   180  	case int32(cb.HeaderType_ORDERER_TRANSACTION):
   181  		env, err := protoutil.UnmarshalEnvelope(payload.Data)
   182  		if err != nil {
   183  			return nil, 0, fmt.Errorf("Abort processing config msg because payload data unmarshalling error: %s", err)
   184  		}
   185  
   186  		configEnvelope := &cb.ConfigEnvelope{}
   187  		_, err = protoutil.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, configEnvelope)
   188  		if err != nil {
   189  			return nil, 0, fmt.Errorf("Abort processing config msg because payload data unmarshalling error: %s", err)
   190  		}
   191  
   192  		return s.ProcessConfigUpdateMsg(configEnvelope.LastUpdate)
   193  
   194  	default:
   195  		return nil, 0, fmt.Errorf("Panic processing config msg due to unexpected envelope type %s", cb.HeaderType_name[chdr.Type])
   196  	}
   197  }
   198  
   199  // DefaultTemplatorSupport is the subset of the channel config required by the DefaultTemplator.
   200  type DefaultTemplatorSupport interface {
   201  	// ConsortiumsConfig returns the ordering system channel's Consortiums config.
   202  	ConsortiumsConfig() (channelconfig.Consortiums, bool)
   203  
   204  	// OrdererConfig returns the ordering configuration and whether the configuration exists
   205  	OrdererConfig() (channelconfig.Orderer, bool)
   206  
   207  	// ConfigtxValidator returns the configtx manager corresponding to the system channel's current config.
   208  	ConfigtxValidator() configtx.Validator
   209  
   210  	// Signer returns the local signer suitable for signing forwarded messages.
   211  	Signer() identity.SignerSerializer
   212  }
   213  
   214  // DefaultTemplator implements the ChannelConfigTemplator interface and is the one used in production deployments.
   215  type DefaultTemplator struct {
   216  	support DefaultTemplatorSupport
   217  	bccsp   bccsp.BCCSP
   218  }
   219  
   220  // NewDefaultTemplator returns an instance of the DefaultTemplator.
   221  func NewDefaultTemplator(support DefaultTemplatorSupport, bccsp bccsp.BCCSP) *DefaultTemplator {
   222  	return &DefaultTemplator{
   223  		support: support,
   224  		bccsp:   bccsp,
   225  	}
   226  }
   227  
   228  // NewChannelConfig creates a new template channel configuration based on the current config in the ordering system channel.
   229  func (dt *DefaultTemplator) NewChannelConfig(envConfigUpdate *cb.Envelope) (channelconfig.Resources, error) {
   230  	configUpdatePayload, err := protoutil.UnmarshalPayload(envConfigUpdate.Payload)
   231  	if err != nil {
   232  		return nil, fmt.Errorf("Failing initial channel config creation because of payload unmarshaling error: %s", err)
   233  	}
   234  
   235  	configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(configUpdatePayload.Data)
   236  	if err != nil {
   237  		return nil, fmt.Errorf("Failing initial channel config creation because of config update envelope unmarshaling error: %s", err)
   238  	}
   239  
   240  	if configUpdatePayload.Header == nil {
   241  		return nil, fmt.Errorf("Failed initial channel config creation because config update header was missing")
   242  	}
   243  
   244  	channelHeader, err := protoutil.UnmarshalChannelHeader(configUpdatePayload.Header.ChannelHeader)
   245  	if err != nil {
   246  		return nil, fmt.Errorf("Failed initial channel config creation because channel header was malformed: %s", err)
   247  	}
   248  
   249  	configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
   250  	if err != nil {
   251  		return nil, fmt.Errorf("Failing initial channel config creation because of config update unmarshaling error: %s", err)
   252  	}
   253  
   254  	if configUpdate.ChannelId != channelHeader.ChannelId {
   255  		return nil, fmt.Errorf("Failing initial channel config creation: mismatched channel IDs: '%s' != '%s'", configUpdate.ChannelId, channelHeader.ChannelId)
   256  	}
   257  
   258  	if configUpdate.WriteSet == nil {
   259  		return nil, fmt.Errorf("Config update has an empty writeset")
   260  	}
   261  
   262  	if configUpdate.WriteSet.Groups == nil || configUpdate.WriteSet.Groups[channelconfig.ApplicationGroupKey] == nil {
   263  		return nil, fmt.Errorf("Config update has missing application group")
   264  	}
   265  
   266  	if uv := configUpdate.WriteSet.Groups[channelconfig.ApplicationGroupKey].Version; uv != 1 {
   267  		return nil, fmt.Errorf("Config update for channel creation does not set application group version to 1, was %d", uv)
   268  	}
   269  
   270  	consortiumConfigValue, ok := configUpdate.WriteSet.Values[channelconfig.ConsortiumKey]
   271  	if !ok {
   272  		return nil, fmt.Errorf("Consortium config value missing")
   273  	}
   274  
   275  	consortium := &cb.Consortium{}
   276  	err = proto.Unmarshal(consortiumConfigValue.Value, consortium)
   277  	if err != nil {
   278  		return nil, fmt.Errorf("Error reading unmarshaling consortium name: %s", err)
   279  	}
   280  
   281  	applicationGroup := protoutil.NewConfigGroup()
   282  	consortiumsConfig, ok := dt.support.ConsortiumsConfig()
   283  	if !ok {
   284  		return nil, fmt.Errorf("The ordering system channel does not appear to resources creating channels")
   285  	}
   286  
   287  	consortiumConf, ok := consortiumsConfig.Consortiums()[consortium.Name]
   288  	if !ok {
   289  		return nil, fmt.Errorf("Unknown consortium name: %s", consortium.Name)
   290  	}
   291  
   292  	policyKey := channelconfig.ChannelCreationPolicyKey
   293  	if oc, ok := dt.support.OrdererConfig(); ok && oc.Capabilities().UseChannelCreationPolicyAsAdmins() {
   294  		// To resources the channel creation process, we use a copy of the Consortium's ChannelCreationPolicy
   295  		// to govern modification of the application group.  We do this by creating a new policy in the
   296  		// Application group (with a copy of the policy info from the consortium) and set the mod policy
   297  		// of the Application group to the name of this policy.  Historically, the name chosen was
   298  		// "ChannelCreationPolicy".  Because this name did not overlap with the default policy names, the
   299  		// creation tx simply encoded the Readers/Writers/Admins policies in the write set at Version 0.
   300  		// However, because there was no /Channel/Application/Admins policy in the template  config,
   301  		// it made evaluating the /Channel/Admins policy impossible.  When the UseChannelCreationPolicyAsAdmins
   302  		// capability is enabled, To allow the /Channel/Admins policy to evaluate normally, we now attempt
   303  		// to use the standard policy name "Admins" instead of "ChannelCreationPolicy", when the user is
   304  		// submitting a configtx generated by a newer version of configtxgen.  We detect if an old
   305  		// configtxgen was used to generate the configtx if the /Channel/Application/Admins policy has a
   306  		//version set to 0.  Otherwise, we use the newer behavior.
   307  		applicationPolicies := configUpdate.WriteSet.Groups[channelconfig.ApplicationGroupKey].Policies
   308  		if applicationPolicies != nil {
   309  			if policy, ok := applicationPolicies[channelconfig.AdminsPolicyKey]; !ok || policy.Version != uint64(0) {
   310  				policyKey = channelconfig.AdminsPolicyKey
   311  			}
   312  		}
   313  	}
   314  	applicationGroup.Policies[policyKey] = &cb.ConfigPolicy{
   315  		Policy:    consortiumConf.ChannelCreationPolicy(),
   316  		ModPolicy: policyKey,
   317  	}
   318  	applicationGroup.ModPolicy = policyKey
   319  
   320  	// Get the current system channel config
   321  	systemChannelGroup := dt.support.ConfigtxValidator().ConfigProto().ChannelGroup
   322  
   323  	// If the consortium group has no members, allow the source request to have no members.  However,
   324  	// if the consortium group has any members, there must be at least one member in the source request
   325  	if len(systemChannelGroup.Groups[channelconfig.ConsortiumsGroupKey].Groups[consortium.Name].Groups) > 0 &&
   326  		len(configUpdate.WriteSet.Groups[channelconfig.ApplicationGroupKey].Groups) == 0 {
   327  		return nil, fmt.Errorf("Proposed configuration has no application group members, but consortium contains members")
   328  	}
   329  
   330  	// If the consortium has no members, allow the source request to contain arbitrary members
   331  	// Otherwise, require that the supplied members are a subset of the consortium members
   332  	if len(systemChannelGroup.Groups[channelconfig.ConsortiumsGroupKey].Groups[consortium.Name].Groups) > 0 {
   333  		for orgName := range configUpdate.WriteSet.Groups[channelconfig.ApplicationGroupKey].Groups {
   334  			consortiumGroup, ok := systemChannelGroup.Groups[channelconfig.ConsortiumsGroupKey].Groups[consortium.Name].Groups[orgName]
   335  			if !ok {
   336  				return nil, fmt.Errorf("Attempted to include a member which is not in the consortium")
   337  			}
   338  			applicationGroup.Groups[orgName] = proto.Clone(consortiumGroup).(*cb.ConfigGroup)
   339  		}
   340  	}
   341  
   342  	channelGroup := protoutil.NewConfigGroup()
   343  
   344  	// Copy the system channel Channel level config to the new config
   345  	for key, value := range systemChannelGroup.Values {
   346  		channelGroup.Values[key] = proto.Clone(value).(*cb.ConfigValue)
   347  		if key == channelconfig.ConsortiumKey {
   348  			// Do not set the consortium name, we do this later
   349  			continue
   350  		}
   351  	}
   352  
   353  	for key, policy := range systemChannelGroup.Policies {
   354  		channelGroup.Policies[key] = proto.Clone(policy).(*cb.ConfigPolicy)
   355  	}
   356  
   357  	// Set the new config orderer group to the system channel orderer group and the application group to the new application group
   358  	channelGroup.Groups[channelconfig.OrdererGroupKey] = proto.Clone(systemChannelGroup.Groups[channelconfig.OrdererGroupKey]).(*cb.ConfigGroup)
   359  	channelGroup.Groups[channelconfig.ApplicationGroupKey] = applicationGroup
   360  	channelGroup.Values[channelconfig.ConsortiumKey] = &cb.ConfigValue{
   361  		Value:     protoutil.MarshalOrPanic(channelconfig.ConsortiumValue(consortium.Name).Value()),
   362  		ModPolicy: channelconfig.AdminsPolicyKey,
   363  	}
   364  
   365  	// Non-backwards compatible bugfix introduced in v1.1
   366  	// The capability check should be removed once v1.0 is deprecated
   367  	if oc, ok := dt.support.OrdererConfig(); ok && oc.Capabilities().PredictableChannelTemplate() {
   368  		channelGroup.ModPolicy = systemChannelGroup.ModPolicy
   369  		zeroVersions(channelGroup)
   370  	}
   371  
   372  	bundle, err := channelconfig.NewBundle(channelHeader.ChannelId, &cb.Config{
   373  		ChannelGroup: channelGroup,
   374  	}, dt.bccsp)
   375  
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  
   380  	return bundle, nil
   381  }
   382  
   383  // zeroVersions recursively iterates over a config tree, setting all versions to zero
   384  func zeroVersions(cg *cb.ConfigGroup) {
   385  	cg.Version = 0
   386  
   387  	for _, value := range cg.Values {
   388  		value.Version = 0
   389  	}
   390  
   391  	for _, policy := range cg.Policies {
   392  		policy.Version = 0
   393  	}
   394  
   395  	for _, group := range cg.Groups {
   396  		zeroVersions(group)
   397  	}
   398  }