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