code: func CreateSignedCCDepSpecForInstall(pack []*common.Envelope) (*common.Envelope, error) {
  	if len(pack) == 0 {
  		return nil, errors.New("no packages provided to collate")
  	}
  
  	//rules...
  	//   all packages must be endorsed or all packages should not be endorsed
  	//   the chaincode deployment spec should be same
  	var baseCip *peer.SignedChaincodeDeploymentSpec
  	var err error
  	var endorsementExists bool
  	var endorsements []*peer.Endorsement
  	for n, r := range pack {
  		p := &common.Payload{}
  		if err = proto.Unmarshal(r.Payload, p); err != nil {
  			return nil, err
  		}
  
  		cip := &peer.SignedChaincodeDeploymentSpec{}
  		if err = proto.Unmarshal(p.Data, cip); err != nil {
  			return nil, err
  		}
  
  		//if its the first element, check if it has endorsement so we can
  		//enforce endorsement rules
  		if n == 0 {
  			baseCip = cip
  			//if it has endorsement, all other owners should have signed too
  			if len(cip.OwnerEndorsements) > 0 {
  				endorsements = make([]*peer.Endorsement, len(pack))
  			}
  
  		} else if err = ValidateCip(baseCip, cip); err != nil {
  			return nil, err
  		}
  
  		if endorsementExists {
  			endorsements[n] = cip.OwnerEndorsements[0]
  		}
  	}
  
  	return createSignedCCDepSpec(baseCip.ChaincodeDeploymentSpec, baseCip.InstantiationPolicy, endorsements)
  }
docs: // CreateSignedCCDepSpecForInstall creates the final package from a set of packages signed by
  // owners.  This is similar to how the SDK assembles a TX from various proposal
  // responses from the signatures.