github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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/configtx"
    23  	configvaluesapi "github.com/hyperledger/fabric/common/configvalues"
    24  	configtxorderer "github.com/hyperledger/fabric/common/configvalues/channel/orderer"
    25  	"github.com/hyperledger/fabric/common/policies"
    26  	"github.com/hyperledger/fabric/orderer/common/filter"
    27  	cb "github.com/hyperledger/fabric/protos/common"
    28  	ab "github.com/hyperledger/fabric/protos/orderer"
    29  	"github.com/hyperledger/fabric/protos/utils"
    30  
    31  	"github.com/golang/protobuf/proto"
    32  )
    33  
    34  // Define some internal interfaces for easier mocking
    35  type chainCreator interface {
    36  	newChain(configTx *cb.Envelope)
    37  }
    38  
    39  type limitedSupport interface {
    40  	PolicyManager() policies.Manager
    41  	SharedConfig() configvaluesapi.Orderer
    42  }
    43  
    44  type systemChainCommitter struct {
    45  	filter   *systemChainFilter
    46  	configTx *cb.Envelope
    47  }
    48  
    49  func (scc *systemChainCommitter) Isolated() bool {
    50  	return true
    51  }
    52  
    53  func (scc *systemChainCommitter) Commit() {
    54  	scc.filter.cc.newChain(scc.configTx)
    55  }
    56  
    57  type systemChainFilter struct {
    58  	cc      chainCreator
    59  	support limitedSupport
    60  }
    61  
    62  func newSystemChainFilter(ls limitedSupport, cc chainCreator) filter.Rule {
    63  	return &systemChainFilter{
    64  		support: ls,
    65  		cc:      cc,
    66  	}
    67  }
    68  
    69  func (scf *systemChainFilter) Apply(env *cb.Envelope) (filter.Action, filter.Committer) {
    70  	msgData := &cb.Payload{}
    71  
    72  	err := proto.Unmarshal(env.Payload, msgData)
    73  	if err != nil {
    74  		return filter.Forward, nil
    75  	}
    76  
    77  	if msgData.Header == nil /* || msgData.Header.ChannelHeader == nil */ {
    78  		return filter.Forward, nil
    79  	}
    80  
    81  	chdr, err := utils.UnmarshalChannelHeader(msgData.Header.ChannelHeader)
    82  	if err != nil {
    83  		return filter.Forward, nil
    84  	}
    85  
    86  	if chdr.Type != int32(cb.HeaderType_ORDERER_TRANSACTION) {
    87  		return filter.Forward, nil
    88  	}
    89  
    90  	configTx := &cb.Envelope{}
    91  	err = proto.Unmarshal(msgData.Data, configTx)
    92  	if err != nil {
    93  		return filter.Reject, nil
    94  	}
    95  
    96  	err = scf.authorizeAndInspect(configTx)
    97  	if err != nil {
    98  		logger.Debugf("Rejecting channel creation because: %s", err)
    99  		return filter.Reject, nil
   100  	}
   101  
   102  	return filter.Accept, &systemChainCommitter{
   103  		filter:   scf,
   104  		configTx: configTx,
   105  	}
   106  }
   107  
   108  func (scf *systemChainFilter) authorize(configEnvelope *cb.ConfigEnvelope) error {
   109  	if configEnvelope.LastUpdate == nil {
   110  		return fmt.Errorf("Must include a config update")
   111  	}
   112  
   113  	configEnvEnvPayload, err := utils.UnmarshalPayload(configEnvelope.LastUpdate.Payload)
   114  	if err != nil {
   115  		return fmt.Errorf("Failing to validate chain creation because of payload unmarshaling error: %s", err)
   116  	}
   117  
   118  	configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(configEnvEnvPayload.Data)
   119  	if err != nil {
   120  		return fmt.Errorf("Failing to validate chain creation because of config update envelope unmarshaling error: %s", err)
   121  	}
   122  
   123  	config, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
   124  	if err != nil {
   125  		return fmt.Errorf("Failing to validate chain creation because of unmarshaling error: %s", err)
   126  	}
   127  
   128  	if config.WriteSet == nil {
   129  		return fmt.Errorf("Failing to validate channel creation because WriteSet is nil")
   130  	}
   131  
   132  	ordererGroup, ok := config.WriteSet.Groups[configtxorderer.GroupKey]
   133  	if !ok {
   134  		return fmt.Errorf("Rejecting channel creation because it is missing orderer group")
   135  	}
   136  
   137  	creationConfigItem, ok := ordererGroup.Values[configtx.CreationPolicyKey]
   138  	if !ok {
   139  		return fmt.Errorf("Failing to validate chain creation because no creation policy included")
   140  	}
   141  
   142  	creationPolicy := &ab.CreationPolicy{}
   143  	err = proto.Unmarshal(creationConfigItem.Value, creationPolicy)
   144  	if err != nil {
   145  		return fmt.Errorf("Failing to validate chain creation because first config item could not unmarshal to a CreationPolicy: %s", err)
   146  	}
   147  
   148  	ok = false
   149  	for _, chainCreatorPolicy := range scf.support.SharedConfig().ChainCreationPolicyNames() {
   150  		if chainCreatorPolicy == creationPolicy.Policy {
   151  			ok = true
   152  			break
   153  		}
   154  	}
   155  
   156  	if !ok {
   157  		return fmt.Errorf("Failed to validate chain creation because chain creation policy (%s) is not authorized for chain creation", creationPolicy.Policy)
   158  	}
   159  
   160  	policy, ok := scf.support.PolicyManager().GetPolicy(creationPolicy.Policy)
   161  	if !ok {
   162  		return fmt.Errorf("Failed to get policy for chain creation despite it being listed as an authorized policy")
   163  	}
   164  
   165  	signedData, err := configUpdateEnv.AsSignedData()
   166  	if err != nil {
   167  		return fmt.Errorf("Failed to validate chain creation because config envelope could not be converted to signed data: %s", err)
   168  	}
   169  
   170  	err = policy.Evaluate(signedData)
   171  	if err != nil {
   172  		return fmt.Errorf("Failed to validate chain creation, did not satisfy policy: %s", err)
   173  	}
   174  
   175  	return nil
   176  }
   177  
   178  func (scf *systemChainFilter) inspect(configResources *configResources) error {
   179  	// XXX decide what it is that we will require to be the same in the new config, and what will be allowed to be different
   180  	// Are all keys allowed? etc.
   181  
   182  	return nil
   183  }
   184  
   185  func (scf *systemChainFilter) authorizeAndInspect(configTx *cb.Envelope) error {
   186  	payload := &cb.Payload{}
   187  	err := proto.Unmarshal(configTx.Payload, payload)
   188  	if err != nil {
   189  		return fmt.Errorf("Rejecting chain proposal: Error unmarshaling envelope payload: %s", err)
   190  	}
   191  
   192  	if payload.Header == nil /* || payload.Header.ChannelHeader == nil */ {
   193  		return fmt.Errorf("Rejecting chain proposal: Not a config transaction")
   194  	}
   195  
   196  	chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   197  	if err != nil {
   198  		return fmt.Errorf("Rejecting chain proposal: Error unmarshaling channel header: %s", err)
   199  	}
   200  
   201  	if chdr.Type != int32(cb.HeaderType_CONFIG) {
   202  		return fmt.Errorf("Rejecting chain proposal: Not a config transaction")
   203  	}
   204  
   205  	configEnvelope := &cb.ConfigEnvelope{}
   206  	err = proto.Unmarshal(payload.Data, configEnvelope)
   207  	if err != nil {
   208  		return fmt.Errorf("Rejecting chain proposal: Error unmarshalling config envelope from payload: %s", err)
   209  	}
   210  
   211  	// Make sure that the config was signed by the appropriate authorized entities
   212  	err = scf.authorize(configEnvelope)
   213  	if err != nil {
   214  		return err
   215  	}
   216  
   217  	configResources, err := newConfigResources(configEnvelope)
   218  	if err != nil {
   219  		return fmt.Errorf("Failed to create config manager and handlers: %s", err)
   220  	}
   221  
   222  	// Make sure that the config does not modify any of the orderer
   223  	return scf.inspect(configResources)
   224  }