github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/common/configvalues/channel/config.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 channel
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  
    23  	api "github.com/hyperledger/fabric/common/configvalues"
    24  	"github.com/hyperledger/fabric/common/configvalues/channel/application"
    25  	"github.com/hyperledger/fabric/common/configvalues/channel/orderer"
    26  	"github.com/hyperledger/fabric/common/util"
    27  	cb "github.com/hyperledger/fabric/protos/common"
    28  
    29  	"github.com/golang/protobuf/proto"
    30  	"github.com/op/go-logging"
    31  )
    32  
    33  var Schema = &cb.ConfigGroupSchema{
    34  	Groups: map[string]*cb.ConfigGroupSchema{
    35  		application.GroupKey: application.Schema,
    36  		orderer.GroupKey:     orderer.Schema,
    37  	},
    38  	Values: map[string]*cb.ConfigValueSchema{
    39  		HashingAlgorithmKey:          nil,
    40  		BlockDataHashingStructureKey: nil,
    41  		OrdererAddressesKey:          nil,
    42  	},
    43  	Policies: map[string]*cb.ConfigPolicySchema{
    44  	// TODO, set appropriately once hierarchical policies are implemented
    45  	},
    46  }
    47  
    48  // Channel config keys
    49  const (
    50  	// HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message
    51  	HashingAlgorithmKey = "HashingAlgorithm"
    52  
    53  	// BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message
    54  	BlockDataHashingStructureKey = "BlockDataHashingStructure"
    55  
    56  	// OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message
    57  	OrdererAddressesKey = "OrdererAddresses"
    58  
    59  	// GroupKey is the name of the channel group
    60  	GroupKey = "Channel"
    61  )
    62  
    63  // Hashing algorithm types
    64  const (
    65  	// SHA3256 is SHA3 with fixed size 256-bit hash
    66  	SHA3256 = "SHA3256"
    67  
    68  	// SHA256 is SHA2 with fixed size 256-bit hash
    69  	SHA256 = "SHA256"
    70  )
    71  
    72  var logger = logging.MustGetLogger("configvalues/channel")
    73  
    74  type ConfigReader interface {
    75  	// HashingAlgorithm returns the default algorithm to be used when hashing
    76  	// such as computing block hashes, and CreationPolicy digests
    77  	HashingAlgorithm() func(input []byte) []byte
    78  
    79  	// BlockDataHashingStructureWidth returns the width to use when constructing the
    80  	// Merkle tree to compute the BlockData hash
    81  	BlockDataHashingStructureWidth() uint32
    82  
    83  	// OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
    84  	OrdererAddresses() []string
    85  }
    86  
    87  type values struct {
    88  	hashingAlgorithm               func(input []byte) []byte
    89  	blockDataHashingStructureWidth uint32
    90  	ordererAddresses               []string
    91  }
    92  
    93  // SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler
    94  // In general, it should only be referenced as an Impl for the configtx.Manager
    95  type Config struct {
    96  	pending *values
    97  	current *values
    98  
    99  	ordererConfig     *orderer.ManagerImpl
   100  	applicationConfig *application.SharedConfigImpl
   101  }
   102  
   103  // NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper
   104  func NewConfig(ordererConfig *orderer.ManagerImpl, applicationConfig *application.SharedConfigImpl) *Config {
   105  	return &Config{
   106  		current:           &values{},
   107  		ordererConfig:     ordererConfig,
   108  		applicationConfig: applicationConfig,
   109  	}
   110  }
   111  
   112  // HashingAlgorithm returns a function pointer to the chain hashing algorihtm
   113  func (c *Config) HashingAlgorithm() func(input []byte) []byte {
   114  	return c.current.hashingAlgorithm
   115  }
   116  
   117  // BlockDataHashingStructure returns the width to use when forming the block data hashing structure
   118  func (c *Config) BlockDataHashingStructureWidth() uint32 {
   119  	return c.current.blockDataHashingStructureWidth
   120  }
   121  
   122  // OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
   123  func (c *Config) OrdererAddresses() []string {
   124  	return c.current.ordererAddresses
   125  }
   126  
   127  // BeginValueProposals is used to start a new config proposal
   128  func (c *Config) BeginValueProposals(groups []string) ([]api.ValueProposer, error) {
   129  	handlers := make([]api.ValueProposer, len(groups))
   130  
   131  	for i, group := range groups {
   132  		switch group {
   133  		case application.GroupKey:
   134  			handlers[i] = c.applicationConfig
   135  		case orderer.GroupKey:
   136  			handlers[i] = c.ordererConfig
   137  		default:
   138  			return nil, fmt.Errorf("Disallowed channel group: %s", group)
   139  		}
   140  	}
   141  
   142  	if c.pending != nil {
   143  		logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
   144  	}
   145  
   146  	c.pending = &values{}
   147  	return handlers, nil
   148  }
   149  
   150  // RollbackProposals is used to abandon a new config proposal
   151  func (c *Config) RollbackProposals() {
   152  	c.pending = nil
   153  }
   154  
   155  // CommitProposals is used to commit a new config proposal
   156  func (c *Config) CommitProposals() {
   157  	if c.pending == nil {
   158  		logger.Panicf("Programming error, cannot call commit without an existing proposal")
   159  	}
   160  	c.current = c.pending
   161  	c.pending = nil
   162  }
   163  
   164  // PreCommit returns nil
   165  func (c *Config) PreCommit() error { return nil }
   166  
   167  // ProposeValue is used to add new config to the config proposal
   168  func (c *Config) ProposeValue(key string, configValue *cb.ConfigValue) error {
   169  	switch key {
   170  	case HashingAlgorithmKey:
   171  		hashingAlgorithm := &cb.HashingAlgorithm{}
   172  		if err := proto.Unmarshal(configValue.Value, hashingAlgorithm); err != nil {
   173  			return fmt.Errorf("Unmarshaling error for HashingAlgorithm: %s", err)
   174  		}
   175  		switch hashingAlgorithm.Name {
   176  		case SHA256:
   177  			c.pending.hashingAlgorithm = util.ComputeSHA256
   178  		case SHA3256:
   179  			c.pending.hashingAlgorithm = util.ComputeSHA3256
   180  		default:
   181  			return fmt.Errorf("Unknown hashing algorithm type: %s", hashingAlgorithm.Name)
   182  		}
   183  	case BlockDataHashingStructureKey:
   184  		blockDataHashingStructure := &cb.BlockDataHashingStructure{}
   185  		if err := proto.Unmarshal(configValue.Value, blockDataHashingStructure); err != nil {
   186  			return fmt.Errorf("Unmarshaling error for BlockDataHashingStructure: %s", err)
   187  		}
   188  
   189  		if blockDataHashingStructure.Width != math.MaxUint32 {
   190  			return fmt.Errorf("BlockDataHashStructure width only supported at MaxUint32 in this version")
   191  		}
   192  
   193  		c.pending.blockDataHashingStructureWidth = blockDataHashingStructure.Width
   194  	case OrdererAddressesKey:
   195  		ordererAddresses := &cb.OrdererAddresses{}
   196  		if err := proto.Unmarshal(configValue.Value, ordererAddresses); err != nil {
   197  			return fmt.Errorf("Unmarshaling error for HashingAlgorithm: %s", err)
   198  		}
   199  		c.pending.ordererAddresses = ordererAddresses.Addresses
   200  	default:
   201  		logger.Warningf("Uknown Chain config item with key %s", key)
   202  	}
   203  	return nil
   204  }