github.com/ewagmig/fabric@v2.1.1+incompatible/common/channelconfig/util_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package channelconfig 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "testing" 13 14 "github.com/golang/protobuf/proto" 15 cb "github.com/hyperledger/fabric-protos-go/common" 16 mspprotos "github.com/hyperledger/fabric-protos-go/msp" 17 ab "github.com/hyperledger/fabric-protos-go/orderer" 18 "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 19 pb "github.com/hyperledger/fabric-protos-go/peer" 20 "github.com/hyperledger/fabric/bccsp/sw" 21 "github.com/hyperledger/fabric/common/capabilities" 22 "github.com/hyperledger/fabric/protoutil" 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 ) 26 27 // The tests in this file are all relatively pointless, as all of this function is exercised 28 // in the normal startup path and things will break horribly if they are broken. 29 // There's additionally really nothing to test without simply re-implementing the function 30 // in the test, which also provides no value. But, not including these produces an artificially 31 // low code coverage count, so here they are. 32 33 func basicTest(t *testing.T, sv *StandardConfigValue) { 34 assert.NotNil(t, sv) 35 assert.NotEmpty(t, sv.Key()) 36 assert.NotNil(t, sv.Value()) 37 } 38 39 func TestUtilsBasic(t *testing.T) { 40 basicTest(t, ConsortiumValue("foo")) 41 basicTest(t, HashingAlgorithmValue()) 42 basicTest(t, BlockDataHashingStructureValue()) 43 basicTest(t, OrdererAddressesValue([]string{"foo:1", "bar:2"})) 44 basicTest(t, ConsensusTypeValue("foo", []byte("bar"))) 45 basicTest(t, BatchSizeValue(1, 2, 3)) 46 basicTest(t, BatchTimeoutValue("1s")) 47 basicTest(t, ChannelRestrictionsValue(7)) 48 basicTest(t, KafkaBrokersValue([]string{"foo:1", "bar:2"})) 49 basicTest(t, MSPValue(&mspprotos.MSPConfig{})) 50 basicTest(t, CapabilitiesValue(map[string]bool{"foo": true, "bar": false})) 51 basicTest(t, AnchorPeersValue([]*pb.AnchorPeer{{}, {}})) 52 basicTest(t, ChannelCreationPolicyValue(&cb.Policy{})) 53 basicTest(t, ACLValues(map[string]string{"foo": "fooval", "bar": "barval"})) 54 } 55 56 // createCfgBlockWithSupportedCapabilities will create a config block that contains valid capabilities and should be accepted by the peer 57 func createCfgBlockWithSupportedCapabilities(t *testing.T) *cb.Block { 58 // Create a config 59 config := &cb.Config{ 60 Sequence: 0, 61 ChannelGroup: protoutil.NewConfigGroup(), 62 } 63 64 // construct the config for top group 65 config.ChannelGroup.Version = 0 66 config.ChannelGroup.ModPolicy = AdminsPolicyKey 67 config.ChannelGroup.Values[BlockDataHashingStructureKey] = &cb.ConfigValue{ 68 Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{ 69 Width: defaultBlockDataHashingStructureWidth, 70 }), 71 ModPolicy: AdminsPolicyKey, 72 } 73 topCapabilities := make(map[string]bool) 74 topCapabilities[capabilities.ChannelV1_1] = true 75 config.ChannelGroup.Values[CapabilitiesKey] = &cb.ConfigValue{ 76 Value: protoutil.MarshalOrPanic(CapabilitiesValue(topCapabilities).Value()), 77 ModPolicy: AdminsPolicyKey, 78 } 79 config.ChannelGroup.Values[ConsortiumKey] = &cb.ConfigValue{ 80 Value: protoutil.MarshalOrPanic(&cb.Consortium{ 81 Name: "testConsortium", 82 }), 83 ModPolicy: AdminsPolicyKey, 84 } 85 config.ChannelGroup.Values[HashingAlgorithmKey] = &cb.ConfigValue{ 86 Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{ 87 Name: defaultHashingAlgorithm, 88 }), 89 ModPolicy: AdminsPolicyKey, 90 } 91 config.ChannelGroup.Values[OrdererAddressesKey] = &cb.ConfigValue{ 92 Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{ 93 Addresses: []string{"orderer.example.com"}, 94 }), 95 ModPolicy: AdminsPolicyKey, 96 } 97 98 // construct the config for Application group 99 config.ChannelGroup.Groups[ApplicationGroupKey] = protoutil.NewConfigGroup() 100 config.ChannelGroup.Groups[ApplicationGroupKey].Version = 0 101 config.ChannelGroup.Groups[ApplicationGroupKey].ModPolicy = AdminsPolicyKey 102 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{} 103 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{} 104 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{} 105 appCapabilities := make(map[string]bool) 106 appCapabilities[capabilities.ApplicationV1_1] = true 107 config.ChannelGroup.Groups[ApplicationGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{ 108 Value: protoutil.MarshalOrPanic(CapabilitiesValue(appCapabilities).Value()), 109 ModPolicy: AdminsPolicyKey, 110 } 111 112 // construct the config for Orderer group 113 config.ChannelGroup.Groups[OrdererGroupKey] = protoutil.NewConfigGroup() 114 config.ChannelGroup.Groups[OrdererGroupKey].Version = 0 115 config.ChannelGroup.Groups[OrdererGroupKey].ModPolicy = AdminsPolicyKey 116 config.ChannelGroup.Groups[OrdererGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{} 117 config.ChannelGroup.Groups[OrdererGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{} 118 config.ChannelGroup.Groups[OrdererGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{} 119 config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchSizeKey] = &cb.ConfigValue{ 120 Value: protoutil.MarshalOrPanic( 121 &ab.BatchSize{ 122 MaxMessageCount: 65535, 123 AbsoluteMaxBytes: 1024000000, 124 PreferredMaxBytes: 1024000000, 125 }), 126 ModPolicy: AdminsPolicyKey, 127 } 128 config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchTimeoutKey] = &cb.ConfigValue{ 129 Value: protoutil.MarshalOrPanic( 130 &ab.BatchTimeout{ 131 Timeout: "2s", 132 }), 133 ModPolicy: AdminsPolicyKey, 134 } 135 ordererCapabilities := make(map[string]bool) 136 ordererCapabilities[capabilities.OrdererV1_1] = true 137 config.ChannelGroup.Groups[OrdererGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{ 138 Value: protoutil.MarshalOrPanic(CapabilitiesValue(ordererCapabilities).Value()), 139 ModPolicy: AdminsPolicyKey, 140 } 141 config.ChannelGroup.Groups[OrdererGroupKey].Values[ConsensusTypeKey] = &cb.ConfigValue{ 142 Value: protoutil.MarshalOrPanic( 143 &ab.ConsensusType{ 144 Type: "solo", 145 }), 146 ModPolicy: AdminsPolicyKey, 147 } 148 149 env := &cb.Envelope{ 150 Payload: protoutil.MarshalOrPanic(&cb.Payload{ 151 Header: &cb.Header{ 152 ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{ 153 ChannelId: "testChain", 154 Type: int32(cb.HeaderType_CONFIG), 155 }), 156 }, 157 Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{ 158 Config: config, 159 }), 160 }), 161 } 162 configBlock := &cb.Block{ 163 Data: &cb.BlockData{ 164 Data: [][]byte{[]byte(protoutil.MarshalOrPanic(env))}, 165 }, 166 } 167 return configBlock 168 } 169 170 // createCfgBlockWithUnSupportedCapabilities will create a config block that contains mismatched capabilities and should be rejected by the peer 171 func createCfgBlockWithUnsupportedCapabilities(t *testing.T) *cb.Block { 172 // Create a config 173 config := &cb.Config{ 174 Sequence: 0, 175 ChannelGroup: protoutil.NewConfigGroup(), 176 } 177 178 // construct the config for top group 179 config.ChannelGroup.Version = 0 180 config.ChannelGroup.ModPolicy = AdminsPolicyKey 181 config.ChannelGroup.Values[BlockDataHashingStructureKey] = &cb.ConfigValue{ 182 Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{ 183 Width: defaultBlockDataHashingStructureWidth, 184 }), 185 ModPolicy: AdminsPolicyKey, 186 } 187 topCapabilities := make(map[string]bool) 188 topCapabilities["INCOMPATIBLE_CAPABILITIES"] = true 189 config.ChannelGroup.Values[CapabilitiesKey] = &cb.ConfigValue{ 190 Value: protoutil.MarshalOrPanic(CapabilitiesValue(topCapabilities).Value()), 191 ModPolicy: AdminsPolicyKey, 192 } 193 config.ChannelGroup.Values[ConsortiumKey] = &cb.ConfigValue{ 194 Value: protoutil.MarshalOrPanic(&cb.Consortium{ 195 Name: "testConsortium", 196 }), 197 ModPolicy: AdminsPolicyKey, 198 } 199 config.ChannelGroup.Values[HashingAlgorithmKey] = &cb.ConfigValue{ 200 Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{ 201 Name: defaultHashingAlgorithm, 202 }), 203 ModPolicy: AdminsPolicyKey, 204 } 205 config.ChannelGroup.Values[OrdererAddressesKey] = &cb.ConfigValue{ 206 Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{ 207 Addresses: []string{"orderer.example.com"}, 208 }), 209 ModPolicy: AdminsPolicyKey, 210 } 211 212 // construct the config for Application group 213 config.ChannelGroup.Groups[ApplicationGroupKey] = protoutil.NewConfigGroup() 214 config.ChannelGroup.Groups[ApplicationGroupKey].Version = 0 215 config.ChannelGroup.Groups[ApplicationGroupKey].ModPolicy = AdminsPolicyKey 216 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{} 217 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{} 218 config.ChannelGroup.Groups[ApplicationGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{} 219 appCapabilities := make(map[string]bool) 220 appCapabilities["INCOMPATIBLE_CAPABILITIES"] = true 221 config.ChannelGroup.Groups[ApplicationGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{ 222 Value: protoutil.MarshalOrPanic(CapabilitiesValue(appCapabilities).Value()), 223 ModPolicy: AdminsPolicyKey, 224 } 225 226 // construct the config for Orderer group 227 config.ChannelGroup.Groups[OrdererGroupKey] = protoutil.NewConfigGroup() 228 config.ChannelGroup.Groups[OrdererGroupKey].Version = 0 229 config.ChannelGroup.Groups[OrdererGroupKey].ModPolicy = AdminsPolicyKey 230 config.ChannelGroup.Groups[OrdererGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{} 231 config.ChannelGroup.Groups[OrdererGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{} 232 config.ChannelGroup.Groups[OrdererGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{} 233 config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchSizeKey] = &cb.ConfigValue{ 234 Value: protoutil.MarshalOrPanic( 235 &ab.BatchSize{ 236 MaxMessageCount: 65535, 237 AbsoluteMaxBytes: 1024000000, 238 PreferredMaxBytes: 1024000000, 239 }), 240 ModPolicy: AdminsPolicyKey, 241 } 242 config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchTimeoutKey] = &cb.ConfigValue{ 243 Value: protoutil.MarshalOrPanic( 244 &ab.BatchTimeout{ 245 Timeout: "2s", 246 }), 247 ModPolicy: AdminsPolicyKey, 248 } 249 ordererCapabilities := make(map[string]bool) 250 ordererCapabilities["INCOMPATIBLE_CAPABILITIES"] = true 251 config.ChannelGroup.Groups[OrdererGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{ 252 Value: protoutil.MarshalOrPanic(CapabilitiesValue(ordererCapabilities).Value()), 253 ModPolicy: AdminsPolicyKey, 254 } 255 config.ChannelGroup.Groups[OrdererGroupKey].Values[ConsensusTypeKey] = &cb.ConfigValue{ 256 Value: protoutil.MarshalOrPanic( 257 &ab.ConsensusType{ 258 Type: "solo", 259 }), 260 ModPolicy: AdminsPolicyKey, 261 } 262 263 env := &cb.Envelope{ 264 Payload: protoutil.MarshalOrPanic(&cb.Payload{ 265 Header: &cb.Header{ 266 ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{ 267 ChannelId: "testChain", 268 Type: int32(cb.HeaderType_CONFIG), 269 }), 270 }, 271 Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{ 272 Config: config, 273 }), 274 }), 275 } 276 configBlock := &cb.Block{ 277 Data: &cb.BlockData{ 278 Data: [][]byte{[]byte(protoutil.MarshalOrPanic(env))}, 279 }, 280 } 281 return configBlock 282 } 283 284 func TestValidateCapabilities(t *testing.T) { 285 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 286 assert.NoError(t, err) 287 288 // Test config block with valid capabilities requirement 289 cfgBlock := createCfgBlockWithSupportedCapabilities(t) 290 err = ValidateCapabilities(cfgBlock, cryptoProvider) 291 assert.NoError(t, err) 292 293 // Test config block with invalid capabilities requirement 294 cfgBlock = createCfgBlockWithUnsupportedCapabilities(t) 295 err = ValidateCapabilities(cfgBlock, cryptoProvider) 296 assert.EqualError(t, err, "Channel capability INCOMPATIBLE_CAPABILITIES is required but not supported") 297 } 298 299 func TestMarshalEtcdRaftMetadata(t *testing.T) { 300 md := &etcdraft.ConfigMetadata{ 301 Consenters: []*etcdraft.Consenter{ 302 { 303 Host: "node-1.example.com", 304 Port: 7050, 305 ClientTlsCert: []byte("testdata/tls-client-1.pem"), 306 ServerTlsCert: []byte("testdata/tls-server-1.pem"), 307 }, 308 { 309 Host: "node-2.example.com", 310 Port: 7050, 311 ClientTlsCert: []byte("testdata/tls-client-2.pem"), 312 ServerTlsCert: []byte("testdata/tls-server-2.pem"), 313 }, 314 { 315 Host: "node-3.example.com", 316 Port: 7050, 317 ClientTlsCert: []byte("testdata/tls-client-3.pem"), 318 ServerTlsCert: []byte("testdata/tls-server-3.pem"), 319 }, 320 }, 321 } 322 packed, err := MarshalEtcdRaftMetadata(md) 323 require.Nil(t, err, "marshalling should succeed") 324 assert.NotNil(t, packed) 325 326 packed, err = MarshalEtcdRaftMetadata(md) 327 require.Nil(t, err, "marshalling should succeed a second time because we did not mutate ourselves") 328 assert.NotNil(t, packed) 329 330 unpacked := &etcdraft.ConfigMetadata{} 331 require.Nil(t, proto.Unmarshal(packed, unpacked), "unmarshalling should succeed") 332 333 var outputCerts, inputCerts [3][]byte 334 for i := range unpacked.GetConsenters() { 335 outputCerts[i] = []byte(unpacked.GetConsenters()[i].GetClientTlsCert()) 336 inputCerts[i], _ = ioutil.ReadFile(fmt.Sprintf("testdata/tls-client-%d.pem", i+1)) 337 338 } 339 340 for i := 0; i < len(inputCerts)-1; i++ { 341 require.NotEqual(t, outputCerts[i+1], outputCerts[i], "expected extracted certs to differ from each other") 342 } 343 }