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