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  }