github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/common/config/channel.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  package config
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  
    23  	"github.com/hyperledger/fabric/bccsp"
    24  	"github.com/hyperledger/fabric/common/config/msp"
    25  	"github.com/hyperledger/fabric/common/util"
    26  	cb "github.com/hyperledger/fabric/protos/common"
    27  )
    28  
    29  // Channel config keys
    30  const (
    31  	// ConsortiumKey is the key for the cb.ConfigValue for the Consortium message
    32  	ConsortiumKey = "Consortium"
    33  
    34  	// HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message
    35  	HashingAlgorithmKey = "HashingAlgorithm"
    36  
    37  	// BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message
    38  	BlockDataHashingStructureKey = "BlockDataHashingStructure"
    39  
    40  	// OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message
    41  	OrdererAddressesKey = "OrdererAddresses"
    42  
    43  	// GroupKey is the name of the channel group
    44  	ChannelGroupKey = "Channel"
    45  )
    46  
    47  // ChannelValues gives read only access to the channel configuration
    48  type ChannelValues interface {
    49  	// HashingAlgorithm returns the default algorithm to be used when hashing
    50  	// such as computing block hashes, and CreationPolicy digests
    51  	HashingAlgorithm() func(input []byte) []byte
    52  
    53  	// BlockDataHashingStructureWidth returns the width to use when constructing the
    54  	// Merkle tree to compute the BlockData hash
    55  	BlockDataHashingStructureWidth() uint32
    56  
    57  	// OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
    58  	OrdererAddresses() []string
    59  }
    60  
    61  // ChannelProtos is where the proposed configuration is unmarshaled into
    62  type ChannelProtos struct {
    63  	HashingAlgorithm          *cb.HashingAlgorithm
    64  	BlockDataHashingStructure *cb.BlockDataHashingStructure
    65  	OrdererAddresses          *cb.OrdererAddresses
    66  	Consortium                *cb.Consortium
    67  }
    68  
    69  type channelConfigSetter struct {
    70  	target **ChannelConfig
    71  	*ChannelConfig
    72  }
    73  
    74  func (ccs *channelConfigSetter) Commit() {
    75  	*(ccs.target) = ccs.ChannelConfig
    76  }
    77  
    78  // ChannelGroup
    79  type ChannelGroup struct {
    80  	*ChannelConfig
    81  	*Proposer
    82  	mspConfigHandler *msp.MSPConfigHandler
    83  }
    84  
    85  func NewChannelGroup(mspConfigHandler *msp.MSPConfigHandler) *ChannelGroup {
    86  	cg := &ChannelGroup{
    87  		ChannelConfig:    NewChannelConfig(),
    88  		mspConfigHandler: mspConfigHandler,
    89  	}
    90  	cg.Proposer = NewProposer(cg)
    91  	return cg
    92  }
    93  
    94  // Allocate creates new config resources for a pending config update
    95  func (cg *ChannelGroup) Allocate() Values {
    96  	return &channelConfigSetter{
    97  		ChannelConfig: NewChannelConfig(),
    98  		target:        &cg.ChannelConfig,
    99  	}
   100  }
   101  
   102  // OrdererConfig returns the orderer config associated with this channel
   103  func (cg *ChannelGroup) OrdererConfig() *OrdererGroup {
   104  	return cg.ChannelConfig.ordererConfig
   105  }
   106  
   107  // ApplicationConfig returns the application config associated with this channel
   108  func (cg *ChannelGroup) ApplicationConfig() *ApplicationGroup {
   109  	return cg.ChannelConfig.appConfig
   110  }
   111  
   112  // ConsortiumsConfig returns the consortium config associated with this channel if it exists
   113  func (cg *ChannelGroup) ConsortiumsConfig() *ConsortiumsGroup {
   114  	return cg.ChannelConfig.consortiumsConfig
   115  }
   116  
   117  // NewGroup instantiates either a new application or orderer config
   118  func (cg *ChannelGroup) NewGroup(group string) (ValueProposer, error) {
   119  	switch group {
   120  	case ApplicationGroupKey:
   121  		return NewApplicationGroup(cg.mspConfigHandler), nil
   122  	case OrdererGroupKey:
   123  		return NewOrdererGroup(cg.mspConfigHandler), nil
   124  	case ConsortiumsGroupKey:
   125  		return NewConsortiumsGroup(cg.mspConfigHandler), nil
   126  	default:
   127  		return nil, fmt.Errorf("Disallowed channel group: %s", group)
   128  	}
   129  }
   130  
   131  // ChannelConfig stores the channel configuration
   132  type ChannelConfig struct {
   133  	*standardValues
   134  	protos *ChannelProtos
   135  
   136  	hashingAlgorithm func(input []byte) []byte
   137  
   138  	appConfig         *ApplicationGroup
   139  	ordererConfig     *OrdererGroup
   140  	consortiumsConfig *ConsortiumsGroup
   141  }
   142  
   143  // NewChannelConfig creates a new ChannelConfig
   144  func NewChannelConfig() *ChannelConfig {
   145  	cc := &ChannelConfig{
   146  		protos: &ChannelProtos{},
   147  	}
   148  
   149  	var err error
   150  	cc.standardValues, err = NewStandardValues(cc.protos)
   151  	if err != nil {
   152  		logger.Panicf("Programming error: %s", err)
   153  	}
   154  	return cc
   155  }
   156  
   157  // HashingAlgorithm returns a function pointer to the chain hashing algorihtm
   158  func (cc *ChannelConfig) HashingAlgorithm() func(input []byte) []byte {
   159  	return cc.hashingAlgorithm
   160  }
   161  
   162  // BlockDataHashingStructure returns the width to use when forming the block data hashing structure
   163  func (cc *ChannelConfig) BlockDataHashingStructureWidth() uint32 {
   164  	return cc.protos.BlockDataHashingStructure.Width
   165  }
   166  
   167  // OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
   168  func (cc *ChannelConfig) OrdererAddresses() []string {
   169  	return cc.protos.OrdererAddresses.Addresses
   170  }
   171  
   172  // ConsortiumName returns the name of the consortium this channel was created under
   173  func (cc *ChannelConfig) ConsortiumName() string {
   174  	return cc.protos.Consortium.Name
   175  }
   176  
   177  // Validate inspects the generated configuration protos, ensures that the values are correct, and
   178  // sets the ChannelConfig fields that may be referenced after Commit
   179  func (cc *ChannelConfig) Validate(tx interface{}, groups map[string]ValueProposer) error {
   180  	for _, validator := range []func() error{
   181  		cc.validateHashingAlgorithm,
   182  		cc.validateBlockDataHashingStructure,
   183  		cc.validateOrdererAddresses,
   184  	} {
   185  		if err := validator(); err != nil {
   186  			return err
   187  		}
   188  	}
   189  
   190  	var ok bool
   191  	for key, value := range groups {
   192  		switch key {
   193  		case ApplicationGroupKey:
   194  			cc.appConfig, ok = value.(*ApplicationGroup)
   195  			if !ok {
   196  				return fmt.Errorf("Application group was not Application config")
   197  			}
   198  		case OrdererGroupKey:
   199  			cc.ordererConfig, ok = value.(*OrdererGroup)
   200  			if !ok {
   201  				return fmt.Errorf("Orderer group was not Orderer config")
   202  			}
   203  		case ConsortiumsGroupKey:
   204  			cc.consortiumsConfig, ok = value.(*ConsortiumsGroup)
   205  			if !ok {
   206  				return fmt.Errorf("Consortiums group was no Consortium config")
   207  			}
   208  		default:
   209  			return fmt.Errorf("Disallowed channel group: %s", key)
   210  		}
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func (cc *ChannelConfig) validateHashingAlgorithm() error {
   217  	switch cc.protos.HashingAlgorithm.Name {
   218  	case bccsp.SHA256:
   219  		cc.hashingAlgorithm = util.ComputeSHA256
   220  	case bccsp.SHA3_256:
   221  		cc.hashingAlgorithm = util.ComputeSHA3256
   222  	default:
   223  		return fmt.Errorf("Unknown hashing algorithm type: %s", cc.protos.HashingAlgorithm.Name)
   224  	}
   225  
   226  	return nil
   227  }
   228  
   229  func (cc *ChannelConfig) validateBlockDataHashingStructure() error {
   230  	if cc.protos.BlockDataHashingStructure.Width != math.MaxUint32 {
   231  		return fmt.Errorf("BlockDataHashStructure width only supported at MaxUint32 in this version")
   232  	}
   233  	return nil
   234  }
   235  
   236  func (cc *ChannelConfig) validateOrdererAddresses() error {
   237  	if len(cc.protos.OrdererAddresses.Addresses) == 0 {
   238  		return fmt.Errorf("Must set some OrdererAddresses")
   239  	}
   240  	return nil
   241  }