github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/orderer/common/multichannel/registrar_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package multichannel 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path" 14 "testing" 15 16 "github.com/golang/protobuf/proto" 17 cb "github.com/hyperledger/fabric-protos-go/common" 18 ab "github.com/hyperledger/fabric-protos-go/orderer" 19 "github.com/osdi23p228/fabric/bccsp/sw" 20 "github.com/osdi23p228/fabric/common/channelconfig" 21 "github.com/osdi23p228/fabric/common/crypto/tlsgen" 22 "github.com/osdi23p228/fabric/common/ledger/blockledger" 23 "github.com/osdi23p228/fabric/common/ledger/blockledger/fileledger" 24 "github.com/osdi23p228/fabric/common/metrics/disabled" 25 "github.com/osdi23p228/fabric/common/policies" 26 "github.com/osdi23p228/fabric/core/config/configtest" 27 "github.com/osdi23p228/fabric/internal/configtxgen/encoder" 28 "github.com/osdi23p228/fabric/internal/configtxgen/genesisconfig" 29 "github.com/osdi23p228/fabric/internal/pkg/identity" 30 "github.com/osdi23p228/fabric/orderer/common/blockcutter" 31 "github.com/osdi23p228/fabric/orderer/common/localconfig" 32 "github.com/osdi23p228/fabric/orderer/common/multichannel/mocks" 33 "github.com/osdi23p228/fabric/orderer/common/types" 34 "github.com/osdi23p228/fabric/orderer/consensus" 35 "github.com/osdi23p228/fabric/protoutil" 36 "github.com/pkg/errors" 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 ) 40 41 //go:generate counterfeiter -o mocks/resources.go --fake-name Resources . resources 42 43 type resources interface { 44 channelconfig.Resources 45 } 46 47 //go:generate counterfeiter -o mocks/orderer_config.go --fake-name OrdererConfig . ordererConfig 48 49 type ordererConfig interface { 50 channelconfig.Orderer 51 } 52 53 //go:generate counterfeiter -o mocks/orderer_capabilities.go --fake-name OrdererCapabilities . ordererCapabilities 54 55 type ordererCapabilities interface { 56 channelconfig.OrdererCapabilities 57 } 58 59 //go:generate counterfeiter -o mocks/channel_config.go --fake-name ChannelConfig . channelConfig 60 61 type channelConfig interface { 62 channelconfig.Channel 63 } 64 65 //go:generate counterfeiter -o mocks/channel_capabilities.go --fake-name ChannelCapabilities . channelCapabilities 66 67 type channelCapabilities interface { 68 channelconfig.ChannelCapabilities 69 } 70 71 //go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer 72 73 type signerSerializer interface { 74 identity.SignerSerializer 75 } 76 77 func mockCrypto() *mocks.SignerSerializer { 78 return &mocks.SignerSerializer{} 79 } 80 81 func newLedgerAndFactory(dir string, chainID string, genesisBlockSys *cb.Block) (blockledger.Factory, blockledger.ReadWriter) { 82 rlf, err := fileledger.New(dir, &disabled.Provider{}) 83 if err != nil { 84 panic(err) 85 } 86 87 rl, err := rlf.GetOrCreate(chainID) 88 if err != nil { 89 panic(err) 90 } 91 92 if genesisBlockSys != nil { 93 err = rl.Append(genesisBlockSys) 94 if err != nil { 95 panic(err) 96 } 97 } 98 return rlf, rl 99 } 100 101 func testMessageOrderAndRetrieval(maxMessageCount uint32, chainID string, chainSupport *ChainSupport, lr blockledger.ReadWriter, t *testing.T) { 102 messages := make([]*cb.Envelope, maxMessageCount) 103 for i := uint32(0); i < maxMessageCount; i++ { 104 messages[i] = makeNormalTx(chainID, int(i)) 105 } 106 for _, message := range messages { 107 chainSupport.Order(message, 0) 108 } 109 it, _ := lr.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}}) 110 defer it.Close() 111 block, status := it.Next() 112 assert.Equal(t, cb.Status_SUCCESS, status, "Could not retrieve block") 113 for i := uint32(0); i < maxMessageCount; i++ { 114 assert.True(t, proto.Equal(messages[i], protoutil.ExtractEnvelopeOrPanic(block, int(i))), "Block contents wrong at index %d", i) 115 } 116 } 117 118 func TestConfigTx(t *testing.T) { 119 // system channel 120 confSys := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 121 genesisBlockSys := encoder.New(confSys).GenesisBlock() 122 123 // Tests for a normal channel which contains 3 config transactions and other 124 // normal transactions to make sure the right one returned 125 t.Run("GetConfigTx - ok", func(t *testing.T) { 126 tmpdir, err := ioutil.TempDir("", "registrar_test-") 127 require.NoError(t, err) 128 defer os.RemoveAll(tmpdir) 129 130 _, rl := newLedgerAndFactory(tmpdir, "testchannelid", genesisBlockSys) 131 for i := 0; i < 5; i++ { 132 rl.Append(blockledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx("testchannelid", i)})) 133 } 134 rl.Append(blockledger.CreateNextBlock(rl, []*cb.Envelope{makeConfigTx("testchannelid", 5)})) 135 ctx := makeConfigTx("testchannelid", 6) 136 rl.Append(blockledger.CreateNextBlock(rl, []*cb.Envelope{ctx})) 137 138 // block with LAST_CONFIG metadata in SIGNATURES field 139 block := blockledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx("testchannelid", 7)}) 140 blockSignatureValue := protoutil.MarshalOrPanic(&cb.OrdererBlockMetadata{ 141 LastConfig: &cb.LastConfig{Index: 7}, 142 }) 143 block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&cb.Metadata{Value: blockSignatureValue}) 144 rl.Append(block) 145 146 pctx := configTx(rl) 147 assert.True(t, proto.Equal(pctx, ctx), "Did not select most recent config transaction") 148 }) 149 } 150 151 func TestNewRegistrar(t *testing.T) { 152 //system channel 153 confSys := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 154 genesisBlockSys := encoder.New(confSys).GenesisBlock() 155 156 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 157 assert.NoError(t, err) 158 159 // This test checks to make sure the orderer can come up if it cannot find any chains 160 t.Run("No chains", func(t *testing.T) { 161 tmpdir, err := ioutil.TempDir("", "registrar_test-") 162 require.NoError(t, err) 163 defer os.RemoveAll(tmpdir) 164 165 lf, err := fileledger.New(tmpdir, &disabled.Provider{}) 166 require.NoError(t, err) 167 168 consenters := make(map[string]consensus.Consenter) 169 consenters["etcdraft"] = &mockConsenter{} 170 171 var manager *Registrar 172 assert.NotPanics(t, func() { 173 manager = NewRegistrar(localconfig.TopLevel{}, lf, mockCrypto(), &disabled.Provider{}, cryptoProvider) 174 manager.Initialize(consenters) 175 }, "Should not panic when starting without a system channel") 176 require.NotNil(t, manager) 177 list := manager.ChannelList() 178 assert.Equal(t, types.ChannelList{}, list) 179 info, err := manager.ChannelInfo("my-channel") 180 assert.EqualError(t, err, types.ErrChannelNotExist.Error()) 181 assert.Equal(t, types.ChannelInfo{}, info) 182 }) 183 184 // This test checks to make sure that the orderer refuses to come up if there are multiple system channels 185 t.Run("Multiple system chains - failure", func(t *testing.T) { 186 tmpdir, err := ioutil.TempDir("", "registrar_test-") 187 require.NoError(t, err) 188 defer os.RemoveAll(tmpdir) 189 190 lf, err := fileledger.New(tmpdir, &disabled.Provider{}) 191 require.NoError(t, err) 192 193 for _, id := range []string{"foo", "bar"} { 194 rl, err := lf.GetOrCreate(id) 195 assert.NoError(t, err) 196 197 err = rl.Append(encoder.New(confSys).GenesisBlockForChannel(id)) 198 assert.NoError(t, err) 199 } 200 201 consenters := make(map[string]consensus.Consenter) 202 consenters[confSys.Orderer.OrdererType] = &mockConsenter{} 203 204 assert.Panics(t, func() { 205 NewRegistrar(localconfig.TopLevel{}, lf, mockCrypto(), &disabled.Provider{}, cryptoProvider).Initialize(consenters) 206 }, "Two system channels should have caused panic") 207 }) 208 209 // This test essentially brings the entire system up and is ultimately what main.go will replicate 210 t.Run("Correct flow with system channel", func(t *testing.T) { 211 tmpdir, err := ioutil.TempDir("", "registrar_test-") 212 require.NoError(t, err) 213 defer os.RemoveAll(tmpdir) 214 215 lf, rl := newLedgerAndFactory(tmpdir, "testchannelid", genesisBlockSys) 216 217 consenters := make(map[string]consensus.Consenter) 218 consenters[confSys.Orderer.OrdererType] = &mockConsenter{} 219 220 manager := NewRegistrar(localconfig.TopLevel{}, lf, mockCrypto(), &disabled.Provider{}, cryptoProvider) 221 manager.Initialize(consenters) 222 223 chainSupport := manager.GetChain("Fake") 224 assert.Nilf(t, chainSupport, "Should not have found a chain that was not created") 225 226 chainSupport = manager.GetChain("testchannelid") 227 assert.NotNilf(t, chainSupport, "Should have gotten chain which was initialized by ledger") 228 229 list := manager.ChannelList() 230 require.NotNil(t, list.SystemChannel) 231 232 assert.Equal( 233 t, 234 types.ChannelList{ 235 SystemChannel: &types.ChannelInfoShort{Name: "testchannelid", URL: ""}, 236 Channels: nil}, 237 list, 238 ) 239 240 info, err := manager.ChannelInfo("testchannelid") 241 assert.NoError(t, err) 242 assert.Equal(t, 243 types.ChannelInfo{Name: "testchannelid", URL: "", ClusterRelation: "none", Status: "active", Height: 1}, 244 info, 245 ) 246 247 testMessageOrderAndRetrieval(confSys.Orderer.BatchSize.MaxMessageCount, "testchannelid", chainSupport, rl, t) 248 }) 249 } 250 251 func TestCreateChain(t *testing.T) { 252 //system channel 253 confSys := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 254 genesisBlockSys := encoder.New(confSys).GenesisBlock() 255 256 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 257 assert.NoError(t, err) 258 259 t.Run("Create chain", func(t *testing.T) { 260 tmpdir, err := ioutil.TempDir("", "registrar_test-") 261 require.NoError(t, err) 262 defer os.RemoveAll(tmpdir) 263 264 lf, _ := newLedgerAndFactory(tmpdir, "testchannelid", genesisBlockSys) 265 266 consenters := make(map[string]consensus.Consenter) 267 consenters[confSys.Orderer.OrdererType] = &mockConsenter{cluster: true} 268 269 manager := NewRegistrar(localconfig.TopLevel{}, lf, mockCrypto(), &disabled.Provider{}, cryptoProvider) 270 manager.Initialize(consenters) 271 272 ledger, err := lf.GetOrCreate("mychannel") 273 assert.NoError(t, err) 274 275 genesisBlock := encoder.New(confSys).GenesisBlockForChannel("mychannel") 276 ledger.Append(genesisBlock) 277 278 // Before creating the chain, it doesn't exist 279 assert.Nil(t, manager.GetChain("mychannel")) 280 // After creating the chain, it exists 281 manager.CreateChain("mychannel") 282 chain := manager.GetChain("mychannel") 283 assert.NotNil(t, chain) 284 285 list := manager.ChannelList() 286 assert.Equal( 287 t, 288 types.ChannelList{ 289 SystemChannel: &types.ChannelInfoShort{Name: "testchannelid", URL: ""}, 290 Channels: []types.ChannelInfoShort{{Name: "mychannel", URL: ""}}}, 291 list, 292 ) 293 294 info, err := manager.ChannelInfo("testchannelid") 295 assert.NoError(t, err) 296 assert.Equal(t, 297 types.ChannelInfo{Name: "testchannelid", URL: "", ClusterRelation: types.ClusterRelationMember, Status: types.StatusActive, Height: 1}, 298 info, 299 ) 300 301 info, err = manager.ChannelInfo("mychannel") 302 assert.NoError(t, err) 303 assert.Equal(t, 304 types.ChannelInfo{Name: "mychannel", URL: "", ClusterRelation: types.ClusterRelationMember, Status: types.StatusActive, Height: 1}, 305 info, 306 ) 307 308 // A subsequent creation, replaces the chain. 309 manager.CreateChain("mychannel") 310 chain2 := manager.GetChain("mychannel") 311 assert.NotNil(t, chain2) 312 // They are not the same 313 assert.NotEqual(t, chain, chain2) 314 // The old chain is halted 315 _, ok := <-chain.Chain.(*mockChainCluster).queue 316 assert.False(t, ok) 317 318 // The new chain is not halted: Close the channel to prove that. 319 close(chain2.Chain.(*mockChainCluster).queue) 320 }) 321 322 // This test brings up the entire system, with the mock consenter, including the broadcasters etc. and creates a new chain 323 t.Run("New chain", func(t *testing.T) { 324 expectedLastConfigSeq := uint64(1) 325 newChainID := "test-new-chain" 326 327 tmpdir, err := ioutil.TempDir("", "registrar_test-") 328 require.NoError(t, err) 329 defer os.RemoveAll(tmpdir) 330 331 lf, rl := newLedgerAndFactory(tmpdir, "testchannelid", genesisBlockSys) 332 333 consenters := make(map[string]consensus.Consenter) 334 consenters[confSys.Orderer.OrdererType] = &mockConsenter{} 335 336 manager := NewRegistrar(localconfig.TopLevel{}, lf, mockCrypto(), &disabled.Provider{}, cryptoProvider) 337 manager.Initialize(consenters) 338 orglessChannelConf := genesisconfig.Load(genesisconfig.SampleSingleMSPChannelProfile, configtest.GetDevConfigDir()) 339 orglessChannelConf.Application.Organizations = nil 340 envConfigUpdate, err := encoder.MakeChannelCreationTransaction(newChainID, mockCrypto(), orglessChannelConf) 341 assert.NoError(t, err, "Constructing chain creation tx") 342 343 res, err := manager.NewChannelConfig(envConfigUpdate) 344 assert.NoError(t, err, "Constructing initial channel config") 345 346 configEnv, err := res.ConfigtxValidator().ProposeConfigUpdate(envConfigUpdate) 347 assert.NoError(t, err, "Proposing initial update") 348 assert.Equal(t, expectedLastConfigSeq, configEnv.GetConfig().Sequence, "Sequence of config envelope for new channel should always be set to %d", expectedLastConfigSeq) 349 350 ingressTx, err := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG, newChainID, mockCrypto(), configEnv, msgVersion, epoch) 351 assert.NoError(t, err, "Creating ingresstx") 352 353 wrapped := wrapConfigTx(ingressTx) 354 355 chainSupport := manager.GetChain(manager.SystemChannelID()) 356 assert.NotNilf(t, chainSupport, "Could not find system channel") 357 358 chainSupport.Configure(wrapped, 0) 359 func() { 360 it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}}) 361 defer it.Close() 362 block, status := it.Next() 363 if status != cb.Status_SUCCESS { 364 t.Fatalf("Could not retrieve block") 365 } 366 if len(block.Data.Data) != 1 { 367 t.Fatalf("Should have had only one message in the orderer transaction block") 368 } 369 370 assert.True(t, proto.Equal(wrapped, protoutil.UnmarshalEnvelopeOrPanic(block.Data.Data[0])), "Orderer config block contains wrong transaction") 371 }() 372 373 chainSupport = manager.GetChain(newChainID) 374 if chainSupport == nil { 375 t.Fatalf("Should have gotten new chain which was created") 376 } 377 378 messages := make([]*cb.Envelope, confSys.Orderer.BatchSize.MaxMessageCount) 379 for i := 0; i < int(confSys.Orderer.BatchSize.MaxMessageCount); i++ { 380 messages[i] = makeNormalTx(newChainID, i) 381 } 382 383 for _, message := range messages { 384 chainSupport.Order(message, 0) 385 } 386 387 it, _ := chainSupport.Reader().Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 0}}}) 388 defer it.Close() 389 block, status := it.Next() 390 if status != cb.Status_SUCCESS { 391 t.Fatalf("Could not retrieve new chain genesis block") 392 } 393 if len(block.Data.Data) != 1 { 394 t.Fatalf("Should have had only one message in the new genesis block") 395 } 396 397 assert.True(t, proto.Equal(ingressTx, protoutil.UnmarshalEnvelopeOrPanic(block.Data.Data[0])), "Genesis block contains wrong transaction") 398 399 block, status = it.Next() 400 if status != cb.Status_SUCCESS { 401 t.Fatalf("Could not retrieve block on new chain") 402 } 403 for i := 0; i < int(confSys.Orderer.BatchSize.MaxMessageCount); i++ { 404 if !proto.Equal(protoutil.ExtractEnvelopeOrPanic(block, i), messages[i]) { 405 t.Errorf("Block contents wrong at index %d in new chain", i) 406 } 407 } 408 409 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 410 assert.NoError(t, err) 411 rcs, err := newChainSupport(manager, chainSupport.ledgerResources, consenters, mockCrypto(), blockcutter.NewMetrics(&disabled.Provider{}), cryptoProvider) 412 assert.NoError(t, err) 413 assert.Equal(t, expectedLastConfigSeq, rcs.lastConfigSeq, "On restart, incorrect lastConfigSeq") 414 }) 415 } 416 417 func TestResourcesCheck(t *testing.T) { 418 mockOrderer := &mocks.OrdererConfig{} 419 mockOrdererCaps := &mocks.OrdererCapabilities{} 420 mockOrderer.CapabilitiesReturns(mockOrdererCaps) 421 mockChannel := &mocks.ChannelConfig{} 422 mockChannelCaps := &mocks.ChannelCapabilities{} 423 mockChannel.CapabilitiesReturns(mockChannelCaps) 424 425 mockResources := &mocks.Resources{} 426 mockResources.PolicyManagerReturns(&policies.ManagerImpl{}) 427 428 t.Run("GoodResources", func(t *testing.T) { 429 mockResources.OrdererConfigReturns(mockOrderer, true) 430 mockResources.ChannelConfigReturns(mockChannel) 431 432 err := checkResources(mockResources) 433 assert.NoError(t, err) 434 }) 435 436 t.Run("MissingOrdererConfigPanic", func(t *testing.T) { 437 mockResources.OrdererConfigReturns(nil, false) 438 439 err := checkResources(mockResources) 440 assert.Error(t, err) 441 assert.Regexp(t, "config does not contain orderer config", err.Error()) 442 }) 443 444 t.Run("MissingOrdererCapability", func(t *testing.T) { 445 mockResources.OrdererConfigReturns(mockOrderer, true) 446 mockOrdererCaps.SupportedReturns(errors.New("An error")) 447 448 err := checkResources(mockResources) 449 assert.Error(t, err) 450 assert.Regexp(t, "config requires unsupported orderer capabilities:", err.Error()) 451 452 // reset 453 mockOrdererCaps.SupportedReturns(nil) 454 }) 455 456 t.Run("MissingChannelCapability", func(t *testing.T) { 457 mockChannelCaps.SupportedReturns(errors.New("An error")) 458 459 err := checkResources(mockResources) 460 assert.Error(t, err) 461 assert.Regexp(t, "config requires unsupported channel capabilities:", err.Error()) 462 }) 463 464 t.Run("MissingOrdererConfigPanic", func(t *testing.T) { 465 mockResources.OrdererConfigReturns(nil, false) 466 467 assert.Panics(t, func() { 468 checkResourcesOrPanic(mockResources) 469 }) 470 }) 471 } 472 473 // The registrar's BroadcastChannelSupport implementation should reject message types which should not be processed directly. 474 func TestBroadcastChannelSupport(t *testing.T) { 475 // system channel 476 confSys := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 477 genesisBlockSys := encoder.New(confSys).GenesisBlock() 478 479 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 480 assert.NoError(t, err) 481 482 t.Run("Rejection", func(t *testing.T) { 483 tmpdir, err := ioutil.TempDir("", "registrar_test-") 484 require.NoError(t, err) 485 defer os.RemoveAll(tmpdir) 486 487 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "testchannelid", genesisBlockSys) 488 mockConsenters := map[string]consensus.Consenter{confSys.Orderer.OrdererType: &mockConsenter{}} 489 registrar := NewRegistrar(localconfig.TopLevel{}, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 490 registrar.Initialize(mockConsenters) 491 randomValue := 1 492 configTx := makeConfigTx("testchannelid", randomValue) 493 _, _, _, err = registrar.BroadcastChannelSupport(configTx) 494 assert.Error(t, err, "Messages of type HeaderType_CONFIG should return an error.") 495 }) 496 497 t.Run("No system channel", func(t *testing.T) { 498 tmpdir, err := ioutil.TempDir("", "registrar_test-") 499 require.NoError(t, err) 500 defer os.RemoveAll(tmpdir) 501 502 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "", nil) 503 mockConsenters := map[string]consensus.Consenter{confSys.Orderer.OrdererType: &mockConsenter{}, "etcdraft": &mockConsenter{}} 504 config := localconfig.TopLevel{} 505 config.General.BootstrapMethod = "none" 506 config.General.GenesisFile = "" 507 registrar := NewRegistrar(config, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 508 registrar.Initialize(mockConsenters) 509 configTx := makeConfigTxFull("testchannelid", 1) 510 _, _, _, err = registrar.BroadcastChannelSupport(configTx) 511 assert.Error(t, err) 512 assert.Equal(t, "channel creation request not allowed because the orderer system channel is not defined", err.Error()) 513 }) 514 } 515 516 func TestRegistrar_JoinChannel(t *testing.T) { 517 // system channel 518 confSys := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 519 genesisBlockSys := encoder.New(confSys).GenesisBlockForChannel("sys-channel") 520 confApp := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir()) 521 confApp.Consortiums = nil 522 confApp.Consortium = "" 523 genesisBlockApp := encoder.New(confApp).GenesisBlockForChannel("my-channel") 524 525 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 526 assert.NoError(t, err) 527 528 t.Run("Reject join when system channel exists", func(t *testing.T) { 529 tmpdir, err := ioutil.TempDir("", "registrar_test-") 530 require.NoError(t, err) 531 defer os.RemoveAll(tmpdir) 532 533 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "sys-channel", genesisBlockSys) 534 mockConsenters := map[string]consensus.Consenter{confSys.Orderer.OrdererType: &mockConsenter{}} 535 registrar := NewRegistrar(localconfig.TopLevel{}, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 536 registrar.Initialize(mockConsenters) 537 538 info, err := registrar.JoinChannel("some-app-channel", &cb.Block{}, true) 539 assert.EqualError(t, err, "system channel exists") 540 assert.Equal(t, types.ChannelInfo{}, info) 541 }) 542 543 t.Run("Reject join when channel exists", func(t *testing.T) { 544 tmpdir, err := ioutil.TempDir("", "registrar_test-") 545 require.NoError(t, err) 546 defer os.RemoveAll(tmpdir) 547 548 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "", nil) 549 mockConsenters := map[string]consensus.Consenter{confSys.Orderer.OrdererType: &mockConsenter{}, "etcdraft": &mockConsenter{}} 550 config := localconfig.TopLevel{} 551 config.General.BootstrapMethod = "none" 552 config.General.GenesisFile = "" 553 registrar := NewRegistrar(config, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 554 registrar.Initialize(mockConsenters) 555 556 ledger, err := ledgerFactory.GetOrCreate("my-channel") 557 assert.NoError(t, err) 558 ledger.Append(genesisBlockApp) 559 560 // Before creating the chain, it doesn't exist 561 assert.Nil(t, registrar.GetChain("my-channel")) 562 // After creating the chain, it exists 563 registrar.CreateChain("my-channel") 564 assert.NotNil(t, registrar.GetChain("my-channel")) 565 566 info, err := registrar.JoinChannel("my-channel", &cb.Block{}, true) 567 assert.EqualError(t, err, "channel already exists") 568 assert.Equal(t, types.ChannelInfo{}, info) 569 }) 570 571 t.Run("Reject system channel join when app channels exist", func(t *testing.T) { 572 tmpdir, err := ioutil.TempDir("", "registrar_test-") 573 require.NoError(t, err) 574 defer os.RemoveAll(tmpdir) 575 576 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "", nil) 577 mockConsenters := map[string]consensus.Consenter{confSys.Orderer.OrdererType: &mockConsenter{}, "etcdraft": &mockConsenter{}} 578 config := localconfig.TopLevel{} 579 config.General.BootstrapMethod = "none" 580 config.General.GenesisFile = "" 581 registrar := NewRegistrar(config, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 582 registrar.Initialize(mockConsenters) 583 584 ledger, err := ledgerFactory.GetOrCreate("my-channel") 585 assert.NoError(t, err) 586 ledger.Append(genesisBlockApp) 587 588 // Before creating the chain, it doesn't exist 589 assert.Nil(t, registrar.GetChain("my-channel")) 590 // After creating the chain, it exists 591 registrar.CreateChain("my-channel") 592 assert.NotNil(t, registrar.GetChain("my-channel")) 593 594 info, err := registrar.JoinChannel("sys-channel", &cb.Block{}, false) 595 assert.EqualError(t, err, "application channels already exist") 596 assert.Equal(t, types.ChannelInfo{}, info) 597 }) 598 599 t.Run("no etcdraft consenter without system channel", func(t *testing.T) { 600 tmpdir, err := ioutil.TempDir("", "registrar_test-") 601 require.NoError(t, err) 602 defer os.RemoveAll(tmpdir) 603 604 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "", nil) 605 mockConsenters := map[string]consensus.Consenter{"not-raft": &mockConsenter{}} 606 607 config := localconfig.TopLevel{} 608 config.General.BootstrapMethod = "none" 609 config.General.GenesisFile = "" 610 registrar := NewRegistrar(config, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 611 612 assert.Panics(t, func() { registrar.Initialize(mockConsenters) }) 613 }) 614 615 t.Run("Join app channel as member without on boarding", func(t *testing.T) { 616 tmpdir, err := ioutil.TempDir("", "registrar_test-") 617 require.NoError(t, err) 618 defer os.RemoveAll(tmpdir) 619 620 tlsCA, _ := tlsgen.NewCA() 621 622 confAppRaft := genesisconfig.Load(genesisconfig.SampleDevModeEtcdRaftProfile, configtest.GetDevConfigDir()) 623 confAppRaft.Consortiums = nil 624 confAppRaft.Consortium = "" 625 generateCertificates(t, confAppRaft, tlsCA, tmpdir) 626 bootstrapper, err := encoder.NewBootstrapper(confAppRaft) 627 require.NoError(t, err, "cannot create bootstrapper") 628 genesisBlockAppRaft := bootstrapper.GenesisBlockForChannel("my-raft-channel") 629 require.NotNil(t, genesisBlockAppRaft) 630 631 ledgerFactory, _ := newLedgerAndFactory(tmpdir, "", nil) 632 mockConsenters := map[string]consensus.Consenter{confAppRaft.Orderer.OrdererType: &mockConsenter{cluster: true}} 633 config := localconfig.TopLevel{} 634 config.General.BootstrapMethod = "none" 635 config.General.GenesisFile = "" 636 registrar := NewRegistrar(config, ledgerFactory, mockCrypto(), &disabled.Provider{}, cryptoProvider) 637 registrar.Initialize(mockConsenters) 638 639 // Before join the chain, it doesn't exist 640 assert.Nil(t, registrar.GetChain("my-raft-channel")) 641 642 info, err := registrar.JoinChannel("my-raft-channel", genesisBlockAppRaft, true) 643 assert.NoError(t, err) 644 assert.Equal(t, types.ChannelInfo{Name: "my-raft-channel", URL: "", ClusterRelation: "member", Status: "active", Height: 0x1}, info) 645 // After creating the chain, it exists 646 assert.NotNil(t, registrar.GetChain("my-raft-channel")) 647 }) 648 } 649 650 func generateCertificates(t *testing.T, confAppRaft *genesisconfig.Profile, tlsCA tlsgen.CA, certDir string) { 651 for i, c := range confAppRaft.Orderer.EtcdRaft.Consenters { 652 srvC, err := tlsCA.NewServerCertKeyPair(c.Host) 653 require.NoError(t, err) 654 srvP := path.Join(certDir, fmt.Sprintf("server%d.crt", i)) 655 err = ioutil.WriteFile(srvP, srvC.Cert, 0644) 656 require.NoError(t, err) 657 658 clnC, err := tlsCA.NewClientCertKeyPair() 659 require.NoError(t, err) 660 clnP := path.Join(certDir, fmt.Sprintf("client%d.crt", i)) 661 err = ioutil.WriteFile(clnP, clnC.Cert, 0644) 662 require.NoError(t, err) 663 664 c.ServerTlsCert = []byte(srvP) 665 c.ClientTlsCert = []byte(clnP) 666 } 667 }