github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/integration/configtx/configtx_test.go (about) 1 /* 2 Copyright IBM Corp All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package configtx 8 9 import ( 10 "crypto" 11 "crypto/x509" 12 "encoding/pem" 13 "io/ioutil" 14 "os" 15 "syscall" 16 "time" 17 18 docker "github.com/fsouza/go-dockerclient" 19 "github.com/golang/protobuf/proto" 20 "github.com/hyperledger/fabric-config/configtx" 21 "github.com/hyperledger/fabric-protos-go/common" 22 "github.com/osdi23p228/fabric/integration/nwo" 23 "github.com/osdi23p228/fabric/integration/nwo/commands" 24 "github.com/tedsuo/ifrit" 25 26 . "github.com/onsi/ginkgo" 27 . "github.com/onsi/gomega" 28 ) 29 30 var _ = Describe("ConfigTx", func() { 31 var ( 32 client *docker.Client 33 testDir string 34 network *nwo.Network 35 process ifrit.Process 36 ) 37 38 BeforeEach(func() { 39 var err error 40 testDir, err = ioutil.TempDir("", "config") 41 Expect(err).NotTo(HaveOccurred()) 42 43 client, err = docker.NewClientFromEnv() 44 Expect(err).NotTo(HaveOccurred()) 45 46 network = nwo.New(nwo.BasicSolo(), testDir, client, StartPort(), components) 47 48 // Generate config 49 network.GenerateConfigTree() 50 51 // bootstrap the network 52 network.Bootstrap() 53 54 networkRunner := network.NetworkGroupRunner() 55 process = ifrit.Invoke(networkRunner) 56 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 57 }) 58 59 AfterEach(func() { 60 if process != nil { 61 process.Signal(syscall.SIGTERM) 62 Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive()) 63 } 64 if network != nil { 65 network.Cleanup() 66 } 67 68 os.RemoveAll(testDir) 69 }) 70 71 It("creates channels and updates them using fabric-config/configtx", func() { 72 orderer := network.Orderer("orderer") 73 org1peer0 := network.Peer("Org1", "peer0") 74 75 By("setting up the channel") 76 channel := configtx.Channel{ 77 Consortium: "SampleConsortium", 78 Application: configtx.Application{ 79 Organizations: []configtx.Organization{ 80 { 81 Name: "Org1", 82 }, 83 { 84 Name: "Org2", 85 }, 86 }, 87 Capabilities: []string{"V1_3"}, 88 ACLs: map[string]string{"event/Block": "/Channel/Application/Readers"}, 89 Policies: map[string]configtx.Policy{ 90 configtx.ReadersPolicyKey: { 91 Type: configtx.ImplicitMetaPolicyType, 92 Rule: "ANY Readers", 93 }, 94 configtx.WritersPolicyKey: { 95 Type: configtx.ImplicitMetaPolicyType, 96 Rule: "ANY Writers", 97 }, 98 configtx.AdminsPolicyKey: { 99 Type: configtx.ImplicitMetaPolicyType, 100 Rule: "MAJORITY Admins", 101 }, 102 configtx.EndorsementPolicyKey: { 103 Type: configtx.ImplicitMetaPolicyType, 104 Rule: "MAJORITY Endorsement", 105 }, 106 configtx.LifecycleEndorsementPolicyKey: { 107 Type: configtx.ImplicitMetaPolicyType, 108 Rule: "MAJORITY Endorsement", 109 }, 110 }, 111 }, 112 } 113 114 channelID := "testchannel" 115 createChannelUpdate, err := configtx.NewMarshaledCreateChannelTx(channel, channelID) 116 Expect(err).NotTo(HaveOccurred()) 117 118 envelope, err := configtx.NewEnvelope(createChannelUpdate) 119 Expect(err).NotTo(HaveOccurred()) 120 envBytes, err := proto.Marshal(envelope) 121 Expect(err).NotTo(HaveOccurred()) 122 channelCreateTxPath := network.CreateChannelTxPath("testchannel") 123 err = ioutil.WriteFile(channelCreateTxPath, envBytes, 0644) 124 Expect(err).NotTo(HaveOccurred()) 125 126 By("creating the channel") 127 createChannel := func() int { 128 sess, err := network.PeerAdminSession(org1peer0, commands.ChannelCreate{ 129 ChannelID: "testchannel", 130 Orderer: network.OrdererAddress(orderer, nwo.ListenPort), 131 File: channelCreateTxPath, 132 OutputBlock: "/dev/null", 133 ClientAuth: network.ClientAuthRequired, 134 }) 135 Expect(err).NotTo(HaveOccurred()) 136 return sess.Wait(network.EventuallyTimeout).ExitCode() 137 } 138 Eventually(createChannel, network.EventuallyTimeout).Should(Equal(0)) 139 140 By("joining all peers to the channel") 141 testPeers := network.PeersWithChannel("testchannel") 142 network.JoinChannel("testchannel", orderer, testPeers...) 143 144 By("getting the current channel config") 145 org2peer0 := network.Peer("Org2", "peer0") 146 channelConfig := nwo.GetConfig(network, org2peer0, orderer, "testchannel") 147 c := configtx.New(channelConfig) 148 149 By("updating orderer channel configuration") 150 o := c.Orderer() 151 oConfig, err := o.Configuration() 152 Expect(err).NotTo(HaveOccurred()) 153 oConfig.BatchTimeout = 2 * time.Second 154 err = o.SetConfiguration(oConfig) 155 Expect(err).NotTo(HaveOccurred()) 156 host, port := OrdererHostPort(network, orderer) 157 err = o.Organization(orderer.Organization).SetEndpoint(configtx.Address{Host: host, Port: port + 1}) 158 Expect(err).NotTo(HaveOccurred()) 159 160 By("computing the config update") 161 configUpdate, err := c.ComputeMarshaledUpdate("testchannel") 162 Expect(err).NotTo(HaveOccurred()) 163 164 By("creating a detached signature for the orderer") 165 signingIdentity := configtx.SigningIdentity{ 166 Certificate: parseOrdererAdminX509Certificate(network, orderer), 167 PrivateKey: parseOrdererAdminPrivateKey(network, orderer), 168 MSPID: network.Organization(orderer.Organization).MSPID, 169 } 170 signature, err := signingIdentity.CreateConfigSignature(configUpdate) 171 Expect(err).NotTo(HaveOccurred()) 172 173 By("creating a signed config update envelope with the orderer's detached signature") 174 configUpdateEnvelope, err := configtx.NewEnvelope(configUpdate, signature) 175 Expect(err).NotTo(HaveOccurred()) 176 err = signingIdentity.SignEnvelope(configUpdateEnvelope) 177 Expect(err).NotTo(HaveOccurred()) 178 179 currentBlockNumber := nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") 180 181 By("submitting the channel config update") 182 resp, err := nwo.Broadcast(network, orderer, configUpdateEnvelope) 183 Expect(err).NotTo(HaveOccurred()) 184 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 185 186 ccb := func() uint64 { return nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") } 187 Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber)) 188 189 By("ensuring the active channel config matches the submitted config") 190 updatedChannelConfig := nwo.GetConfig(network, org2peer0, orderer, "testchannel") 191 Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue()) 192 193 By("checking the current application capabilities") 194 c = configtx.New(updatedChannelConfig) 195 a := c.Application() 196 capabilities, err := a.Capabilities() 197 Expect(err).NotTo(HaveOccurred()) 198 Expect(capabilities).To(HaveLen(1)) 199 Expect(capabilities).To(ContainElement("V1_3")) 200 201 By("enabling V2_0 application capabilities") 202 err = a.AddCapability("V2_0") 203 Expect(err).NotTo(HaveOccurred()) 204 205 By("checking the application capabilities after update") 206 capabilities, err = a.Capabilities() 207 Expect(err).NotTo(HaveOccurred()) 208 Expect(capabilities).To(HaveLen(2)) 209 Expect(capabilities).To(ContainElements("V1_3", "V2_0")) 210 211 By("computing the config update") 212 configUpdate, err = c.ComputeMarshaledUpdate("testchannel") 213 Expect(err).NotTo(HaveOccurred()) 214 215 By("creating detached signatures for each peer") 216 signingIdentities := make([]configtx.SigningIdentity, len(testPeers)) 217 signatures := make([]*common.ConfigSignature, len(testPeers)) 218 for i, p := range testPeers { 219 signingIdentity := configtx.SigningIdentity{ 220 Certificate: parsePeerAdminX509Certificate(network, p), 221 PrivateKey: parsePeerAdminPrivateKey(network, p), 222 MSPID: network.Organization(p.Organization).MSPID, 223 } 224 signingIdentities[i] = signingIdentity 225 signature, err := signingIdentity.CreateConfigSignature(configUpdate) 226 Expect(err).NotTo(HaveOccurred()) 227 signatures[i] = signature 228 } 229 230 By("creating a signed config update envelope with the detached peer signatures") 231 configUpdateEnvelope, err = configtx.NewEnvelope(configUpdate, signatures...) 232 Expect(err).NotTo(HaveOccurred()) 233 err = signingIdentities[0].SignEnvelope(configUpdateEnvelope) 234 Expect(err).NotTo(HaveOccurred()) 235 236 currentBlockNumber = nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") 237 238 By("submitting the channel config update") 239 resp, err = nwo.Broadcast(network, orderer, configUpdateEnvelope) 240 Expect(err).NotTo(HaveOccurred()) 241 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 242 243 ccb = func() uint64 { return nwo.CurrentConfigBlockNumber(network, org2peer0, orderer, "testchannel") } 244 Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber)) 245 246 By("ensuring the active channel config matches the submitted config") 247 updatedChannelConfig = nwo.GetConfig(network, org2peer0, orderer, "testchannel") 248 Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue()) 249 250 By("adding the anchor peer for each org") 251 for _, peer := range network.AnchorsForChannel("testchannel") { 252 By("getting the current channel config") 253 channelConfig = nwo.GetConfig(network, peer, orderer, "testchannel") 254 c = configtx.New(channelConfig) 255 peerOrg := c.Application().Organization(peer.Organization) 256 257 By("adding the anchor peer for " + peer.Organization) 258 host, port := PeerHostPort(network, peer) 259 err = peerOrg.AddAnchorPeer(configtx.Address{Host: host, Port: port}) 260 Expect(err).NotTo(HaveOccurred()) 261 262 By("computing the config update") 263 configUpdate, err = c.ComputeMarshaledUpdate("testchannel") 264 Expect(err).NotTo(HaveOccurred()) 265 266 By("creating a detached signature") 267 signingIdentity := configtx.SigningIdentity{ 268 Certificate: parsePeerAdminX509Certificate(network, peer), 269 PrivateKey: parsePeerAdminPrivateKey(network, peer), 270 MSPID: network.Organization(peer.Organization).MSPID, 271 } 272 signature, err := signingIdentity.CreateConfigSignature(configUpdate) 273 Expect(err).NotTo(HaveOccurred()) 274 275 By("creating a signed config update envelope with the detached peer signature") 276 configUpdateEnvelope, err = configtx.NewEnvelope(configUpdate, signature) 277 Expect(err).NotTo(HaveOccurred()) 278 err = signingIdentity.SignEnvelope(configUpdateEnvelope) 279 Expect(err).NotTo(HaveOccurred()) 280 281 currentBlockNumber = nwo.CurrentConfigBlockNumber(network, peer, orderer, "testchannel") 282 283 By("submitting the channel config update for " + peer.Organization) 284 resp, err = nwo.Broadcast(network, orderer, configUpdateEnvelope) 285 Expect(err).NotTo(HaveOccurred()) 286 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 287 288 ccb = func() uint64 { return nwo.CurrentConfigBlockNumber(network, peer, orderer, "testchannel") } 289 Eventually(ccb, network.EventuallyTimeout).Should(BeNumerically(">", currentBlockNumber)) 290 291 By("ensuring the active channel config matches the submitted config") 292 updatedChannelConfig = nwo.GetConfig(network, peer, orderer, "testchannel") 293 Expect(proto.Equal(c.UpdatedConfig(), updatedChannelConfig)).To(BeTrue()) 294 } 295 }) 296 }) 297 298 func parsePeerAdminX509Certificate(n *nwo.Network, p *nwo.Peer) *x509.Certificate { 299 return parseCertificate(n.PeerUserCert(p, "Admin")) 300 } 301 302 func parseOrdererAdminX509Certificate(n *nwo.Network, o *nwo.Orderer) *x509.Certificate { 303 return parseCertificate(n.OrdererUserCert(o, "Admin")) 304 } 305 306 func parseCertificate(filename string) *x509.Certificate { 307 certBytes, err := ioutil.ReadFile(filename) 308 Expect(err).NotTo(HaveOccurred()) 309 pemBlock, _ := pem.Decode(certBytes) 310 cert, err := x509.ParseCertificate(pemBlock.Bytes) 311 Expect(err).NotTo(HaveOccurred()) 312 return cert 313 } 314 315 func parsePeerAdminPrivateKey(n *nwo.Network, p *nwo.Peer) crypto.PrivateKey { 316 return parsePrivateKey(n.PeerUserKey(p, "Admin")) 317 } 318 319 func parseOrdererAdminPrivateKey(n *nwo.Network, o *nwo.Orderer) crypto.PrivateKey { 320 return parsePrivateKey(n.OrdererUserKey(o, "Admin")) 321 } 322 323 func parsePrivateKey(filename string) crypto.PrivateKey { 324 pkBytes, err := ioutil.ReadFile(filename) 325 Expect(err).NotTo(HaveOccurred()) 326 pemBlock, _ := pem.Decode(pkBytes) 327 privateKey, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes) 328 Expect(err).NotTo(HaveOccurred()) 329 return privateKey 330 }