diff --git a/integration/raft/channel_participation_test.go b/integration/raft/channel_participation_test.go index 563f11d349f..da4195fe54e 100644 --- a/integration/raft/channel_participation_test.go +++ b/integration/raft/channel_participation_test.go @@ -133,7 +133,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(cl).To(Equal(channelparticipation.ChannelList{})) } - genesisBlock := applicationChannelGenesisBlock(network, consenters, peer, "participation-trophy") + genesisBlock := applicationChannelGenesisBlock(network, consenters, []*nwo.Peer{peer}, "participation-trophy") expectedChannelInfoPT := channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", @@ -149,7 +149,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(channelInfo).To(Equal(expectedChannelInfoPT)) } - submitPeerTxn(orderer1, peer, network, consenters, 1, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -157,7 +157,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 2, }) - submitPeerTxn(orderer2, peer, network, consenters, 2, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -199,7 +199,7 @@ var _ = Describe("ChannelParticipation", func() { }, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPT)) By("submitting transaction to orderer3 to ensure it is active") - submitPeerTxn(orderer3, peer, network, orderers, 4, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -208,7 +208,7 @@ var _ = Describe("ChannelParticipation", func() { }) By("joining orderer1 to another channel as a consenter") - genesisBlockAPT := applicationChannelGenesisBlock(network, []*nwo.Orderer{orderer1}, peer, "another-participation-trophy") + genesisBlockAPT := applicationChannelGenesisBlock(network, []*nwo.Orderer{orderer1}, []*nwo.Peer{peer}, "another-participation-trophy") expectedChannelInfoAPT := channelparticipation.ChannelInfo{ Name: "another-participation-trophy", URL: "/participation/v1/channels/another-participation-trophy", @@ -243,7 +243,7 @@ var _ = Describe("ChannelParticipation", func() { })) consenters = []*nwo.Orderer{orderer2, orderer3} - submitPeerTxn(orderer2, peer, network, consenters, 6, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -287,7 +287,7 @@ var _ = Describe("ChannelParticipation", func() { channelparticipation.ChannelListMatcher(cl, []string{"another-participation-trophy"}) By("ensuring the channel is still usable by submitting a transaction to each remaining consenter for the channel") - submitPeerTxn(orderer2, peer, network, consenters, 7, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -295,7 +295,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 8, }) - submitPeerTxn(orderer3, peer, network, consenters, 8, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -332,7 +332,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(cl).To(Equal(channelparticipation.ChannelList{})) } - genesisBlock := applicationChannelGenesisBlock(network, orderers, peer, "participation-trophy") + genesisBlock := applicationChannelGenesisBlock(network, orderers, []*nwo.Peer{peer}, "participation-trophy") expectedChannelInfoPT := channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", @@ -348,7 +348,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(channelInfo).To(Equal(expectedChannelInfoPT)) } - submitPeerTxn(orderer1, peer, network, orderers, 1, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -356,7 +356,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 2, }) - submitPeerTxn(orderer2, peer, network, orderers, 2, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -405,7 +405,7 @@ var _ = Describe("ChannelParticipation", func() { return channelparticipation.ListOne(network, orderer3, "participation-trophy") }, network.EventuallyTimeout).Should(Equal(expectedChannelInfoConsenter)) - submitPeerTxn(orderer3, peer, network, orderers, 5, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -428,7 +428,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(cl).To(Equal(channelparticipation.ChannelList{})) } - genesisBlock := applicationChannelGenesisBlock(network, orderers, peer, "participation-trophy") + genesisBlock := applicationChannelGenesisBlock(network, orderers, []*nwo.Peer{peer}, "participation-trophy") expectedChannelInfoPT := channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", @@ -444,7 +444,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(channelInfo).To(Equal(expectedChannelInfoPT)) } - submitPeerTxn(orderer1, peer, network, orderers, 1, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -452,7 +452,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 2, }) - submitPeerTxn(orderer2, peer, network, orderers, 2, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -508,7 +508,7 @@ var _ = Describe("ChannelParticipation", func() { return channelparticipation.ListOne(network, orderer3, "participation-trophy") }, network.EventuallyTimeout).Should(Equal(expectedChannelInfoPT)) - submitPeerTxn(orderer3, peer, network, orderers, 5, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -517,21 +517,21 @@ var _ = Describe("ChannelParticipation", func() { }) }) - It("creates the system channel with a genesis block", func() { - peer := network.Peer("Org1", "peer0") + It("creates the system channel on two orderers with a genesis block and joins a third using a config block", func() { orderer1 := network.Orderer("orderer1") orderer2 := network.Orderer("orderer2") orderer3 := network.Orderer("orderer3") + orderers1and2 := []*nwo.Orderer{orderer1, orderer2} orderers := []*nwo.Orderer{orderer1, orderer2, orderer3} + org1peer0 := network.Peer("Org1", "peer0") + org2peer0 := network.Peer("Org2", "peer0") + peers := []*nwo.Peer{org1peer0, org2peer0} + for _, o := range orderers { startOrderer(o) } - systemChannelBlockBytes, err := ioutil.ReadFile(network.OutputBlockPath("systemchannel")) - Expect(err).NotTo(HaveOccurred()) - systemChannelBlock := &common.Block{} - err = proto.Unmarshal(systemChannelBlockBytes, systemChannelBlock) - Expect(err).NotTo(HaveOccurred()) + systemChannelGenesisBlock := systemChannelGenesisBlock(network, orderers1and2, peers, network.SystemChannel.Name) expectedChannelInfo := channelparticipation.ChannelInfo{ Name: "systemchannel", @@ -542,27 +542,27 @@ var _ = Describe("ChannelParticipation", func() { } By("joining orderers to systemchannel") - for _, o := range orderers { - channelparticipation.Join(network, o, "systemchannel", systemChannelBlock, expectedChannelInfo) + for _, o := range orderers1and2 { + channelparticipation.Join(network, o, "systemchannel", systemChannelGenesisBlock, expectedChannelInfo) } By("attempting to join a channel when system channel is present") - channelparticipationJoinFailure(network, orderer1, "systemchannel", systemChannelBlock, http.StatusMethodNotAllowed, "cannot join: system channel exists") + channelparticipationJoinFailure(network, orderer1, "systemchannel", systemChannelGenesisBlock, http.StatusMethodNotAllowed, "cannot join: system channel exists") By("ensuring the system channel is unusable before restarting by attempting to submit a transaction") - for _, o := range orderers { + for _, o := range orderers1and2 { By("submitting transaction to " + o.Name) - env := CreateBroadcastEnvelope(network, peer, "systemchannel", []byte("hello")) + env := CreateBroadcastEnvelope(network, org1peer0, "systemchannel", []byte("hello")) Expect(broadcastTransactionFunc(network, o, env)()).To(Equal(common.Status_FORBIDDEN)) } - By("restarting all orderers") - for i, o := range orderers { + By("restarting all orderers in the system channel") + for i, o := range orderers1and2 { restartOrderer(o, i) } By("creating a channel") - network.CreateChannel("testchannel", orderer1, peer) + network.CreateChannel("testchannel", orderer1, org1peer0) expectedChannelInfo = channelparticipation.ChannelInfo{ Name: "testchannel", @@ -571,14 +571,14 @@ var _ = Describe("ChannelParticipation", func() { ConsensusRelation: "consenter", Height: 1, } - for _, o := range orderers { + for _, o := range orderers1and2 { By("listing single channel for " + o.Name) Eventually(func() channelparticipation.ChannelInfo { return channelparticipation.ListOne(network, o, "testchannel") }, network.EventuallyTimeout).Should(Equal(expectedChannelInfo)) } - for _, o := range orderers { + for _, o := range orderers1and2 { By("listing the channels for " + o.Name) cl := channelparticipation.List(network, o) channelparticipation.ChannelListMatcher(cl, []string{"testchannel"}, []string{"systemchannel"}...) @@ -591,6 +591,88 @@ var _ = Describe("ChannelParticipation", func() { ConsensusRelation: "consenter", Height: 2, } + for _, o := range orderers1and2 { + By("listing single channel for " + o.Name) + Eventually(func() channelparticipation.ChannelInfo { + return channelparticipation.ListOne(network, o, "systemchannel") + }, network.EventuallyTimeout).Should(Equal(expectedChannelInfo)) + } + + By("submitting transaction to each active orderer to confirm channel is usable") + submitPeerTxn(orderer1, org1peer0, network, channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 2, + }) + + submitPeerTxn(orderer2, org1peer0, network, channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 3, + }) + + By("submitting a channel config update for the system channel") + channelConfig := nwo.GetConfig(network, org1peer0, orderer1, "systemchannel") + c := configtx.New(channelConfig) + err := c.Orderer().SetBatchTimeout(4 * time.Second) + Expect(err).NotTo(HaveOccurred()) + err = c.Orderer().AddConsenter(consenterChannelConfig(network, orderer3)) + Expect(err).NotTo(HaveOccurred()) + computeSignSubmitConfigUpdate(network, orderer1, org1peer0, c, "systemchannel") + currentBlockNumber := nwo.CurrentConfigBlockNumber(network, org1peer0, orderer1, "systemchannel") + Expect(currentBlockNumber).To(BeNumerically(">", 1)) + + By("joining orderer3 to the system channel") + // make sure we can join using a config block from one of the other orderers + configBlockSC := nwo.GetConfigBlock(network, org1peer0, orderer2, "systemchannel") + expectedChannelInfo = channelparticipation.ChannelInfo{ + Name: "systemchannel", + URL: "/participation/v1/channels/systemchannel", + Status: "inactive", + ConsensusRelation: "consenter", + Height: 0, + } + channelparticipation.Join(network, orderer3, "systemchannel", configBlockSC, expectedChannelInfo) + + By("restarting orderer3") + restartOrderer(orderer3, 2) + + By("listing the channels for orderer3") + cl := channelparticipation.List(network, orderer3) + channelparticipation.ChannelListMatcher(cl, []string{"testchannel"}, []string{"systemchannel"}...) + + By("ensuring orderer3 catches up to the latest height as an active consenter") + expectedChannelInfo.Status = "active" + expectedChannelInfo.Height = 3 + Eventually(func() channelparticipation.ChannelInfo { + return channelparticipation.ListOne(network, orderer3, "systemchannel") + }, network.EventuallyTimeout).Should(Equal(expectedChannelInfo)) + + By("submitting a channel config update to add orderer3 to the endpoints") + channelConfig = nwo.GetConfig(network, org1peer0, orderer1, "systemchannel") + c = configtx.New(channelConfig) + host, port := conftx.OrdererHostPort(network, orderer3) + err = c.Orderer().Organization(orderer3.Organization).SetEndpoint( + configtx.Address{ + Host: host, + Port: port, + }, + ) + Expect(err).NotTo(HaveOccurred()) + computeSignSubmitConfigUpdate(network, orderer2, org1peer0, c, "systemchannel") + + By("ensuring all orderers are active consenters for the system channel") + expectedChannelInfo = channelparticipation.ChannelInfo{ + Name: "systemchannel", + URL: "/participation/v1/channels/systemchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 4, + } for _, o := range orderers { By("listing single channel for " + o.Name) Eventually(func() channelparticipation.ChannelInfo { @@ -598,9 +680,56 @@ var _ = Describe("ChannelParticipation", func() { }, network.EventuallyTimeout).Should(Equal(expectedChannelInfo)) } - By("submitting transaction to orderer to confirm channel is usable") - env := CreateBroadcastEnvelope(network, peer, "testchannel", []byte("hello")) - Eventually(broadcastTransactionFunc(network, orderer1, env), network.EventuallyTimeout).Should(Equal(common.Status_SUCCESS)) + By("adding orderer3 to the consenters set and endpoints of the application channel") + channelConfig = nwo.GetConfig(network, org1peer0, orderer1, "testchannel") + c = configtx.New(channelConfig) + err = c.Orderer().AddConsenter(consenterChannelConfig(network, orderer3)) + Expect(err).NotTo(HaveOccurred()) + err = c.Orderer().Organization(orderer3.Organization).SetEndpoint( + configtx.Address{ + Host: host, + Port: port, + }, + ) + Expect(err).NotTo(HaveOccurred()) + computeSignSubmitConfigUpdate(network, orderer1, org1peer0, c, "testchannel") + + By("ensuring orderer3 becomes an active consenter for the application channel") + expectedChannelInfo = channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 4, + } + Eventually(func() channelparticipation.ChannelInfo { + return channelparticipation.ListOne(network, orderer3, "testchannel") + }, network.EventuallyTimeout).Should(Equal(expectedChannelInfo)) + + By("submitting transactions to ensure the application channel is usable") + submitPeerTxn(orderer3, org1peer0, network, channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 5, + }) + + submitPeerTxn(orderer2, org1peer0, network, channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 6, + }) + + submitPeerTxn(orderer1, org1peer0, network, channelparticipation.ChannelInfo{ + Name: "testchannel", + URL: "/participation/v1/channels/testchannel", + Status: "active", + ConsensusRelation: "consenter", + Height: 7, + }) }) }) @@ -675,7 +804,7 @@ var _ = Describe("ChannelParticipation", func() { } By("submitting a transaction to ensure the system channel is active after restart") - submitOrdererTxn(orderer2, peer, network, orderers, 2, channelparticipation.ChannelInfo{ + submitOrdererTxn(orderer2, network, channelparticipation.ChannelInfo{ Name: "systemchannel", URL: "/participation/v1/channels/systemchannel", Status: "active", @@ -684,7 +813,7 @@ var _ = Describe("ChannelParticipation", func() { }) By("submitting a transaction to ensure the application channel is active after restart") - submitPeerTxn(orderer2, peer, network, orderers, 4, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "testchannel", URL: "/participation/v1/channels/testchannel", Status: "active", @@ -725,7 +854,7 @@ var _ = Describe("ChannelParticipation", func() { } By("submitting a transaction to each active orderer") - submitPeerTxn(orderer1, peer, network, orderers1and2, 6, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "testchannel", URL: "/participation/v1/channels/testchannel", Status: "active", @@ -733,7 +862,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 7, }) - submitPeerTxn(orderer2, peer, network, orderers1and2, 7, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "testchannel", URL: "/participation/v1/channels/testchannel", Status: "active", @@ -754,14 +883,14 @@ var _ = Describe("ChannelParticipation", func() { })) By("attempting to join a channel when the system channel is present") - genesisBlock := applicationChannelGenesisBlock(network, orderers, peer, "participation-trophy") + genesisBlock := applicationChannelGenesisBlock(network, orderers, []*nwo.Peer{peer}, "participation-trophy") channelparticipationJoinFailure(network, orderers[0], "participation-trophy", genesisBlock, http.StatusMethodNotAllowed, "cannot join: system channel exists") By("attempting to remove a channel when the system channel is present") channelparticipationRemoveFailure(network, orderers[0], "testchannel", http.StatusMethodNotAllowed, "cannot remove: system channel exists") By("submitting a transaction to ensure the system channel is active after restart") - submitOrdererTxn(orderer3, peer, network, orderers, 3, channelparticipation.ChannelInfo{ + submitOrdererTxn(orderer3, network, channelparticipation.ChannelInfo{ Name: "systemchannel", URL: "/participation/v1/channels/systemchannel", Status: "active", @@ -788,7 +917,7 @@ var _ = Describe("ChannelParticipation", func() { } By("submitting a transaction to each active orderer after restart") - submitPeerTxn(orderer1, peer, network, orderers1and2, 8, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "testchannel", URL: "/participation/v1/channels/testchannel", Status: "active", @@ -796,7 +925,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 9, }) - submitPeerTxn(orderer2, peer, network, orderers1and2, 9, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "testchannel", URL: "/participation/v1/channels/testchannel", Status: "active", @@ -820,7 +949,7 @@ var _ = Describe("ChannelParticipation", func() { Expect(channelInfo).To(Equal(expectedChannelInfoPT)) } - submitPeerTxn(orderer1, peer, network, orderers, 1, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer1, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -828,7 +957,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 2, }) - submitPeerTxn(orderer2, peer, network, orderers, 2, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer2, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -836,7 +965,7 @@ var _ = Describe("ChannelParticipation", func() { Height: 3, }) - submitPeerTxn(orderer3, peer, network, orderers, 3, channelparticipation.ChannelInfo{ + submitPeerTxn(orderer3, peer, network, channelparticipation.ChannelInfo{ Name: "participation-trophy", URL: "/participation/v1/channels/participation-trophy", Status: "active", @@ -845,26 +974,25 @@ var _ = Describe("ChannelParticipation", func() { }) }) }) - }) // submit a transaction signed by the peer and ensure it was // committed to the ledger -func submitPeerTxn(o *nwo.Orderer, peer *nwo.Peer, n *nwo.Network, orderers []*nwo.Orderer, expectedBlkNum int, expectedChannelInfo channelparticipation.ChannelInfo) { +func submitPeerTxn(o *nwo.Orderer, peer *nwo.Peer, n *nwo.Network, expectedChannelInfo channelparticipation.ChannelInfo) { env := CreateBroadcastEnvelope(n, peer, expectedChannelInfo.Name, []byte("hello")) - submitTxn(o, env, peer, n, orderers, expectedBlkNum, expectedChannelInfo) + submitTxn(o, env, n, expectedChannelInfo) } // submit a transaction signed by the orderer and ensure it is // committed to the ledger -func submitOrdererTxn(o *nwo.Orderer, peer *nwo.Peer, n *nwo.Network, orderers []*nwo.Orderer, expectedBlkNum int, expectedChannelInfo channelparticipation.ChannelInfo) { +func submitOrdererTxn(o *nwo.Orderer, n *nwo.Network, expectedChannelInfo channelparticipation.ChannelInfo) { env := CreateBroadcastEnvelope(n, o, expectedChannelInfo.Name, []byte("hello")) - submitTxn(o, env, peer, n, orderers, expectedBlkNum, expectedChannelInfo) + submitTxn(o, env, n, expectedChannelInfo) } // submit the envelope to the orderer and ensure it is committed // to the ledger -func submitTxn(o *nwo.Orderer, env *common.Envelope, peer *nwo.Peer, n *nwo.Network, orderers []*nwo.Orderer, expectedBlkNum int, expectedChannelInfo channelparticipation.ChannelInfo) { +func submitTxn(o *nwo.Orderer, env *common.Envelope, n *nwo.Network, expectedChannelInfo channelparticipation.ChannelInfo) { By("submitting a transaction to " + o.Name) Eventually(broadcastTransactionFunc(n, o, env), n.EventuallyTimeout, time.Second).Should(Equal(common.Status_SUCCESS)) @@ -874,9 +1002,9 @@ func submitTxn(o *nwo.Orderer, env *common.Envelope, peer *nwo.Peer, n *nwo.Netw }, n.EventuallyTimeout).Should(Equal(expectedChannelInfo)) } -func applicationChannelGenesisBlock(n *nwo.Network, orderers []*nwo.Orderer, p *nwo.Peer, channel string) *common.Block { +func applicationChannelGenesisBlock(n *nwo.Network, orderers []*nwo.Orderer, peers []*nwo.Peer, channel string) *common.Block { ordererOrgs, consenters := ordererOrganizationsAndConsenters(n, orderers) - peerOrgs := peerOrganizations(n, p) + peerOrgs := peerOrganizations(n, peers) channelConfig := configtx.Channel{ Orderer: configtx.Orderer{ @@ -968,6 +1096,80 @@ func applicationChannelGenesisBlock(n *nwo.Network, orderers []*nwo.Orderer, p * return genesisBlock } +func systemChannelGenesisBlock(n *nwo.Network, orderers []*nwo.Orderer, peers []*nwo.Peer, channel string) *common.Block { + ordererOrgs, consenters := ordererOrganizationsAndConsenters(n, orderers) + peerOrgs := peerOrganizations(n, peers) + + channelConfig := configtx.Channel{ + Orderer: configtx.Orderer{ + OrdererType: "etcdraft", + Organizations: ordererOrgs, + EtcdRaft: orderer.EtcdRaft{ + Consenters: consenters, + Options: orderer.EtcdRaftOptions{ + TickInterval: "500ms", + ElectionTick: 10, + HeartbeatTick: 1, + MaxInflightBlocks: 5, + SnapshotIntervalSize: 16 * 1024 * 1024, // 16 MB + }, + }, + Policies: map[string]configtx.Policy{ + "Readers": { + Type: "ImplicitMeta", + Rule: "ANY Readers", + }, + "Writers": { + Type: "ImplicitMeta", + Rule: "ANY Writers", + }, + "Admins": { + Type: "ImplicitMeta", + Rule: "MAJORITY Admins", + }, + "BlockValidation": { + Type: "ImplicitMeta", + Rule: "ANY Writers", + }, + }, + Capabilities: []string{"V2_0"}, + BatchSize: orderer.BatchSize{ + MaxMessageCount: 100, + AbsoluteMaxBytes: 1024 * 1024, + PreferredMaxBytes: 512 * 1024, + }, + BatchTimeout: 2 * time.Second, + State: "STATE_NORMAL", + }, + Consortiums: []configtx.Consortium{ + { + Name: n.Consortiums[0].Name, + Organizations: peerOrgs, + }, + }, + Capabilities: []string{"V2_0"}, + Policies: map[string]configtx.Policy{ + "Readers": { + Type: "ImplicitMeta", + Rule: "ANY Readers", + }, + "Writers": { + Type: "ImplicitMeta", + Rule: "ANY Writers", + }, + "Admins": { + Type: "ImplicitMeta", + Rule: "MAJORITY Admins", + }, + }, + } + + genesisBlock, err := configtx.NewSystemChannelGenesisBlock(channelConfig, channel) + Expect(err).NotTo(HaveOccurred()) + + return genesisBlock +} + // parseCertificate loads the PEM-encoded x509 certificate at the specified // path. func parseCertificate(path string) *x509.Certificate { @@ -1004,7 +1206,7 @@ func ordererOrganizationsAndConsenters(n *nwo.Network, orderers []*nwo.Orderer) orgConfig.OrdererEndpoints = []string{ n.OrdererAddress(o, nwo.ListenPort), } - ordererOrgsMap[o.Organization] = orgConfig + ordererOrgsMap[o.Organization] = &orgConfig } else { orgConfig.OrdererEndpoints = append(orgConfig.OrdererEndpoints, n.OrdererAddress(o, nwo.ListenPort)) orgConfig.MSP.RootCerts = append(orgConfig.MSP.RootCerts, rootCert) @@ -1023,18 +1225,23 @@ func ordererOrganizationsAndConsenters(n *nwo.Network, orderers []*nwo.Orderer) return ordererOrgs, consenters } -func peerOrganizations(n *nwo.Network, p *nwo.Peer) []configtx.Organization { - rootCert := parseCertificate(n.PeerCACert(p)) - adminCert := parseCertificate(n.PeerUserCert(p, "Admin")) - tlsRootCert := parseCertificate(filepath.Join(n.PeerLocalTLSDir(p), "ca.crt")) +// constructs the peer organizations for a config block. It should be passed +// only one peer per organization. +func peerOrganizations(n *nwo.Network, peers []*nwo.Peer) []configtx.Organization { + peerOrgs := make([]configtx.Organization, len(peers)) + for i, p := range peers { + rootCert := parseCertificate(n.PeerCACert(p)) + adminCert := parseCertificate(n.PeerUserCert(p, "Admin")) + tlsRootCert := parseCertificate(filepath.Join(n.PeerLocalTLSDir(p), "ca.crt")) - peerOrg := configtxOrganization(n.Organization(p.Organization), rootCert, adminCert, tlsRootCert) + peerOrgs[i] = configtxOrganization(n.Organization(p.Organization), rootCert, adminCert, tlsRootCert) + } - return []configtx.Organization{*peerOrg} + return peerOrgs } -func configtxOrganization(org *nwo.Organization, rootCert, adminCert, tlsRootCert *x509.Certificate) *configtx.Organization { - orgConfig := &configtx.Organization{ +func configtxOrganization(org *nwo.Organization, rootCert, adminCert, tlsRootCert *x509.Certificate) configtx.Organization { + return configtx.Organization{ Name: org.Name, Policies: map[string]configtx.Policy{ "Readers": { @@ -1047,7 +1254,7 @@ func configtxOrganization(org *nwo.Organization, rootCert, adminCert, tlsRootCer }, "Admins": { Type: "Signature", - Rule: fmt.Sprintf("OR('%s.member')", org.MSPID), + Rule: fmt.Sprintf("OR('%s.admin')", org.MSPID), }, }, MSP: configtx.MSP{ @@ -1057,8 +1264,6 @@ func configtxOrganization(org *nwo.Organization, rootCert, adminCert, tlsRootCer TLSRootCerts: []*x509.Certificate{tlsRootCert}, }, } - - return orgConfig } func computeSignSubmitConfigUpdate(n *nwo.Network, o *nwo.Orderer, p *nwo.Peer, c configtx.ConfigTx, channel string) {