github.com/ewagmig/fabric@v2.1.1+incompatible/integration/e2e/instantiation_policy_test.go (about) 1 /* 2 Copyright IBM Corp All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package e2e 8 9 import ( 10 "crypto/sha256" 11 "encoding/hex" 12 "io/ioutil" 13 "os" 14 "syscall" 15 "time" 16 17 docker "github.com/fsouza/go-dockerclient" 18 "github.com/golang/protobuf/proto" 19 "github.com/golang/protobuf/ptypes" 20 "github.com/hyperledger/fabric-protos-go/common" 21 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 22 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 23 "github.com/hyperledger/fabric-protos-go/peer" 24 "github.com/hyperledger/fabric/cmd/common/signer" 25 "github.com/hyperledger/fabric/common/policydsl" 26 "github.com/hyperledger/fabric/integration/nwo" 27 "github.com/hyperledger/fabric/integration/nwo/commands" 28 29 . "github.com/onsi/ginkgo" 30 . "github.com/onsi/gomega" 31 "github.com/onsi/gomega/gbytes" 32 "github.com/onsi/gomega/gexec" 33 "github.com/tedsuo/ifrit" 34 ) 35 36 var _ = Describe("InstantiationPolicy", func() { 37 var ( 38 testDir string 39 client *docker.Client 40 network *nwo.Network 41 process ifrit.Process 42 ) 43 44 BeforeEach(func() { 45 var err error 46 testDir, err = ioutil.TempDir("", "e2e") 47 Expect(err).NotTo(HaveOccurred()) 48 49 client, err = docker.NewClientFromEnv() 50 Expect(err).NotTo(HaveOccurred()) 51 }) 52 53 AfterEach(func() { 54 if process != nil { 55 process.Signal(syscall.SIGTERM) 56 Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive()) 57 } 58 if network != nil { 59 network.Cleanup() 60 } 61 os.RemoveAll(testDir) 62 }) 63 64 Describe("single node etcdraft network with single peer", func() { 65 BeforeEach(func() { 66 config := nwo.MinimalRaft() 67 config.Profiles[1].Organizations = []string{"Org1", "Org2"} 68 network = nwo.New(config, testDir, client, StartPort(), components) 69 network.GenerateConfigTree() 70 network.Bootstrap() 71 72 networkRunner := network.NetworkGroupRunner() 73 process = ifrit.Invoke(networkRunner) 74 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 75 }) 76 77 It("honors the instantiation policy", func() { 78 orderer := network.Orderer("orderer") 79 80 org1Peer := network.Peer("Org1", "peer0") 81 org2Peer := network.Peer("Org2", "peer0") 82 83 network.CreateAndJoinChannel(orderer, "testchannel") 84 85 By("attempting to deploy with an unsatisfied instantiation policy") 86 87 goodDeploy := LSCCOperation{ 88 Operation: "deploy", 89 ChannelID: "testchannel", 90 Name: "fakecc", 91 Version: "badip", 92 InstantiationOrgs: []*nwo.Organization{ 93 network.Organization("Org2"), 94 }, 95 } 96 97 nwo.Broadcast(network, orderer, goodDeploy.Tx(PeerSigner(network, org1Peer))) 98 99 nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 2, org1Peer) 100 101 Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).NotTo(gbytes.Say("Name: fakecc, Version: badip")) 102 103 By("attempting to deploy with a satisfied instantiation policy") 104 105 badDeploy := LSCCOperation{ 106 Operation: "deploy", 107 ChannelID: "testchannel", 108 Name: "fakecc", 109 Version: "goodip", 110 InstantiationOrgs: []*nwo.Organization{ 111 network.Organization("Org1"), 112 }, 113 } 114 115 nwo.Broadcast(network, orderer, badDeploy.Tx(PeerSigner(network, org1Peer))) 116 117 nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 3, org1Peer) 118 Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).To(gbytes.Say("Name: fakecc, Version: goodip")) 119 120 By("upgrading without satisfying the previous instantiation policy") 121 122 badUpgrade := LSCCOperation{ 123 Operation: "upgrade", 124 ChannelID: "testchannel", 125 Name: "fakecc", 126 Version: "wrongsubmitter", 127 InstantiationOrgs: []*nwo.Organization{ 128 network.Organization("Org2"), 129 }, 130 } 131 132 nwo.Broadcast(network, orderer, badUpgrade.Tx(PeerSigner(network, org2Peer))) 133 134 nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 4, org1Peer) 135 Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).NotTo(gbytes.Say("Name: fakecc, Version: wrongsubmitter")) 136 137 By("upgrading while satisfying the previous instantiation policy") 138 139 goodUpgrade := LSCCOperation{ 140 Operation: "upgrade", 141 ChannelID: "testchannel", 142 Name: "fakecc", 143 Version: "rightsubmitter", 144 InstantiationOrgs: []*nwo.Organization{ 145 network.Organization("Org1"), 146 }, 147 } 148 149 nwo.Broadcast(network, orderer, goodUpgrade.Tx(PeerSigner(network, org1Peer))) 150 151 nwo.WaitUntilEqualLedgerHeight(network, "testchannel", 5, org1Peer) 152 Expect(ListInstantiatedLegacy(network, org1Peer, "testchannel")).To(gbytes.Say("Name: fakecc, Version: rightsubmitter")) 153 }) 154 }) 155 156 }) 157 158 func PeerSigner(n *nwo.Network, p *nwo.Peer) *signer.Signer { 159 conf := signer.Config{ 160 MSPID: n.Organization(p.Organization).MSPID, 161 IdentityPath: n.PeerUserCert(p, "Admin"), 162 KeyPath: n.PeerUserKey(p, "Admin"), 163 } 164 165 signer, err := signer.NewSigner(conf) 166 Expect(err).NotTo(HaveOccurred()) 167 168 return signer 169 } 170 171 func MarshalOrPanic(msg proto.Message) []byte { 172 b, err := proto.Marshal(msg) 173 if err != nil { 174 panic(err) 175 } 176 return b 177 } 178 179 func ListInstantiatedLegacy(n *nwo.Network, p *nwo.Peer, channel string) *gbytes.Buffer { 180 sess, err := n.PeerAdminSession(p, commands.ChaincodeListInstantiatedLegacy{ 181 ChannelID: channel, 182 ClientAuth: n.ClientAuthRequired, 183 }) 184 Expect(err).NotTo(HaveOccurred()) 185 Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0)) 186 return sess.Buffer() 187 } 188 189 type LSCCOperation struct { 190 Operation string 191 ChannelID string 192 Name string 193 Version string 194 InstantiationOrgs []*nwo.Organization 195 } 196 197 func (lo *LSCCOperation) Tx(signer *signer.Signer) *common.Envelope { 198 creatorBytes, err := signer.Serialize() 199 Expect(err).NotTo(HaveOccurred()) 200 201 var instantiationMSPIDs []string 202 for _, org := range lo.InstantiationOrgs { 203 instantiationMSPIDs = append(instantiationMSPIDs, org.MSPID) 204 } 205 instantiationPolicy := policydsl.SignedByAnyMember(instantiationMSPIDs) 206 207 nonce, err := time.Now().MarshalBinary() 208 Expect(err).NotTo(HaveOccurred()) 209 210 timestamp, err := ptypes.TimestampProto(time.Now().UTC()) 211 Expect(err).NotTo(HaveOccurred()) 212 213 hasher := sha256.New() 214 hasher.Write(nonce) 215 hasher.Write(creatorBytes) 216 txid := hex.EncodeToString(hasher.Sum(nil)) 217 218 signatureHeaderBytes := MarshalOrPanic(&common.SignatureHeader{ 219 Creator: creatorBytes, 220 Nonce: nonce, 221 }) 222 223 channelHeaderBytes := MarshalOrPanic(&common.ChannelHeader{ 224 ChannelId: lo.ChannelID, 225 Extension: MarshalOrPanic(&peer.ChaincodeHeaderExtension{ 226 ChaincodeId: &peer.ChaincodeID{ 227 Name: "lscc", 228 }, 229 }), 230 Timestamp: timestamp, 231 TxId: txid, 232 Type: int32(common.HeaderType_ENDORSER_TRANSACTION), 233 }) 234 235 chaincodeDataBytes := MarshalOrPanic(&peer.ChaincodeData{ 236 Data: []byte("a-big-bunch-of-fakery"), 237 Id: []byte("a-friendly-fake-chaincode"), 238 Escc: "escc", 239 Vscc: "vscc", 240 Name: lo.Name, 241 Version: lo.Version, 242 InstantiationPolicy: instantiationPolicy, 243 Policy: nil, // EndorsementPolicy deliberately left nil 244 }) 245 246 proposalPayloadBytes := MarshalOrPanic(&peer.ChaincodeProposalPayload{ 247 Input: MarshalOrPanic(&peer.ChaincodeInvocationSpec{ 248 ChaincodeSpec: &peer.ChaincodeSpec{ 249 Input: &peer.ChaincodeInput{ 250 Args: [][]byte{ 251 []byte(lo.Operation), 252 []byte(lo.ChannelID), 253 MarshalOrPanic(&peer.ChaincodeDeploymentSpec{ 254 ChaincodeSpec: &peer.ChaincodeSpec{ 255 ChaincodeId: &peer.ChaincodeID{ 256 Name: lo.Name, 257 Version: lo.Version, 258 }, 259 Input: &peer.ChaincodeInput{ 260 Args: [][]byte{[]byte("bogus-init-arg")}, 261 }, 262 Type: peer.ChaincodeSpec_GOLANG, 263 }, 264 }), 265 {}, // Endorsement policy bytes deliberately empty 266 []byte("escc"), 267 []byte("vscc"), 268 }, 269 }, 270 Type: peer.ChaincodeSpec_GOLANG, 271 }, 272 }), 273 }) 274 275 propHash := sha256.New() 276 propHash.Write(channelHeaderBytes) 277 propHash.Write(signatureHeaderBytes) 278 propHash.Write(proposalPayloadBytes) 279 proposalHash := propHash.Sum(nil)[:] 280 281 proposalResponsePayloadBytes := MarshalOrPanic(&peer.ProposalResponsePayload{ 282 ProposalHash: proposalHash, 283 Extension: MarshalOrPanic(&peer.ChaincodeAction{ 284 ChaincodeId: &peer.ChaincodeID{ 285 Name: "lscc", 286 Version: "syscc", 287 }, 288 Events: MarshalOrPanic(&peer.ChaincodeEvent{ 289 ChaincodeId: "lscc", 290 EventName: lo.Operation, 291 Payload: MarshalOrPanic(&peer.LifecycleEvent{ 292 ChaincodeName: lo.Name, 293 }), 294 }), 295 Response: &peer.Response{ 296 Payload: chaincodeDataBytes, 297 Status: 200, 298 }, 299 Results: MarshalOrPanic(&rwset.TxReadWriteSet{ 300 DataModel: rwset.TxReadWriteSet_KV, 301 NsRwset: []*rwset.NsReadWriteSet{ 302 { 303 Namespace: "lscc", 304 Rwset: MarshalOrPanic(&kvrwset.KVRWSet{ 305 Writes: []*kvrwset.KVWrite{ 306 { 307 Key: lo.Name, 308 Value: chaincodeDataBytes, 309 }, 310 }, 311 }), 312 }, 313 { 314 Namespace: lo.Name, 315 Rwset: MarshalOrPanic(&kvrwset.KVRWSet{ 316 Writes: []*kvrwset.KVWrite{ 317 { 318 Key: "bogus-key", 319 Value: []byte("bogus-value"), 320 }, 321 }, 322 }), 323 }, 324 }, 325 }), 326 }), 327 }) 328 329 endorsementSignature, err := signer.Sign(append(proposalResponsePayloadBytes, creatorBytes...)) 330 Expect(err).NotTo(HaveOccurred()) 331 332 payloadBytes := MarshalOrPanic(&common.Payload{ 333 Header: &common.Header{ 334 ChannelHeader: channelHeaderBytes, 335 SignatureHeader: signatureHeaderBytes, 336 }, 337 Data: MarshalOrPanic(&peer.Transaction{ 338 Actions: []*peer.TransactionAction{ 339 { 340 Header: signatureHeaderBytes, 341 Payload: MarshalOrPanic(&peer.ChaincodeActionPayload{ 342 ChaincodeProposalPayload: proposalPayloadBytes, 343 Action: &peer.ChaincodeEndorsedAction{ 344 ProposalResponsePayload: proposalResponsePayloadBytes, 345 Endorsements: []*peer.Endorsement{ 346 { 347 Endorser: creatorBytes, 348 Signature: endorsementSignature, 349 }, 350 }, 351 }, 352 }), 353 }, 354 }, 355 }), 356 }) 357 358 envSignature, err := signer.Sign(payloadBytes) 359 Expect(err).NotTo(HaveOccurred()) 360 361 return &common.Envelope{ 362 Payload: payloadBytes, 363 Signature: envSignature, 364 } 365 }