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 }