github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/core/ledger/kvledger/tests/util.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tests
     8  
     9  import (
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    16  	"github.com/hyperledger/fabric-protos-go/msp"
    17  	protopeer "github.com/hyperledger/fabric-protos-go/peer"
    18  	"github.com/hyperledger/fabric/common/cauthdsl"
    19  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    20  	"github.com/hyperledger/fabric/common/crypto"
    21  	"github.com/hyperledger/fabric/common/flogging"
    22  	"github.com/hyperledger/fabric/common/metrics/disabled"
    23  	"github.com/hyperledger/fabric/core/ledger/kvledger/tests/fakes"
    24  	lutils "github.com/hyperledger/fabric/core/ledger/util"
    25  	"github.com/hyperledger/fabric/core/ledger/util/couchdb"
    26  	"github.com/hyperledger/fabric/integration/runner"
    27  	"github.com/hyperledger/fabric/protoutil"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  var logger = flogging.MustGetLogger("test2")
    32  
    33  // collConf helps writing tests with less verbose code by specifying coll configuration
    34  // in a simple struct in place of 'peer.CollectionConfigPackage'. (the test heplers' apis
    35  // use 'collConf' as parameters and return values and transform back and forth to/from proto
    36  // message internally (using func 'convertToCollConfigProtoBytes' and 'convertFromCollConfigProto')
    37  type collConf struct {
    38  	name    string
    39  	btl     uint64
    40  	members []string
    41  }
    42  
    43  type txAndPvtdata struct {
    44  	Txid     string
    45  	Envelope *common.Envelope
    46  	Pvtws    *rwset.TxPvtReadWriteSet
    47  }
    48  
    49  //go:generate counterfeiter -o fakes/signer.go --fake-name Signer . signer
    50  
    51  type signer interface {
    52  	Sign(msg []byte) ([]byte, error)
    53  	Serialize() ([]byte, error)
    54  }
    55  
    56  func convertToCollConfigProtoBytes(collConfs []*collConf) ([]byte, error) {
    57  	var protoConfArray []*protopeer.CollectionConfig
    58  	for _, c := range collConfs {
    59  		protoConf := &protopeer.CollectionConfig{
    60  			Payload: &protopeer.CollectionConfig_StaticCollectionConfig{
    61  				StaticCollectionConfig: &protopeer.StaticCollectionConfig{
    62  					Name:             c.name,
    63  					BlockToLive:      c.btl,
    64  					MemberOrgsPolicy: convertToMemberOrgsPolicy(c.members),
    65  				},
    66  			},
    67  		}
    68  		protoConfArray = append(protoConfArray, protoConf)
    69  	}
    70  	return proto.Marshal(&protopeer.CollectionConfigPackage{Config: protoConfArray})
    71  }
    72  
    73  func convertToMemberOrgsPolicy(members []string) *protopeer.CollectionPolicyConfig {
    74  	var data [][]byte
    75  	for _, member := range members {
    76  		data = append(data, []byte(member))
    77  	}
    78  	return &protopeer.CollectionPolicyConfig{
    79  		Payload: &protopeer.CollectionPolicyConfig_SignaturePolicy{
    80  			SignaturePolicy: cauthdsl.Envelope(cauthdsl.Or(cauthdsl.SignedBy(0), cauthdsl.SignedBy(1)), data),
    81  		},
    82  	}
    83  }
    84  
    85  func convertFromMemberOrgsPolicy(policy *protopeer.CollectionPolicyConfig) []string {
    86  	if policy.GetSignaturePolicy() == nil {
    87  		return nil
    88  	}
    89  	ids := policy.GetSignaturePolicy().Identities
    90  	var members []string
    91  	for _, id := range ids {
    92  		role := &msp.MSPRole{}
    93  		err := proto.Unmarshal(id.Principal, role)
    94  		if err == nil {
    95  			// This is for sample ledger generated by fabric (e.g., integration test),
    96  			// where id.Principal was properly marshalled during sample ledger generation.
    97  			members = append(members, role.MspIdentifier)
    98  		} else {
    99  			// This is for sample ledger generated by sampleDataHelper.populateLedger,
   100  			// where id.Principal was a []byte cast from a string (not a marshalled msp.MSPRole)
   101  			members = append(members, string(id.Principal))
   102  		}
   103  	}
   104  	return members
   105  }
   106  
   107  func convertFromCollConfigProto(collConfPkg *protopeer.CollectionConfigPackage) []*collConf {
   108  	var collConfs []*collConf
   109  	protoConfArray := collConfPkg.Config
   110  	for _, protoConf := range protoConfArray {
   111  		p := protoConf.GetStaticCollectionConfig()
   112  		collConfs = append(collConfs,
   113  			&collConf{
   114  				name:    p.Name,
   115  				btl:     p.BlockToLive,
   116  				members: convertFromMemberOrgsPolicy(p.MemberOrgsPolicy),
   117  			},
   118  		)
   119  	}
   120  	return collConfs
   121  }
   122  
   123  func constructTransaction(txid string, simulationResults []byte) (*common.Envelope, error) {
   124  	channelid := "dummyChannel"
   125  	ccid := &protopeer.ChaincodeID{
   126  		Name:    "dummyCC",
   127  		Version: "dummyVer",
   128  	}
   129  	txenv, _, err := constructUnsignedTxEnv(
   130  		channelid,
   131  		ccid,
   132  		&protopeer.Response{Status: 200},
   133  		simulationResults,
   134  		txid,
   135  		nil,
   136  		nil,
   137  		common.HeaderType_ENDORSER_TRANSACTION,
   138  	)
   139  	return txenv, err
   140  }
   141  
   142  // constructUnsignedTxEnv creates a Transaction envelope from given inputs
   143  func constructUnsignedTxEnv(
   144  	channelID string,
   145  	ccid *protopeer.ChaincodeID,
   146  	response *protopeer.Response,
   147  	simulationResults []byte,
   148  	txid string,
   149  	events []byte,
   150  	visibility []byte,
   151  	headerType common.HeaderType,
   152  ) (*common.Envelope, string, error) {
   153  
   154  	sigID := &fakes.Signer{}
   155  	sigID.SerializeReturns([]byte("signer"), nil)
   156  	sigID.SignReturns([]byte("signature"), nil)
   157  
   158  	ss, err := sigID.Serialize()
   159  	if err != nil {
   160  		return nil, "", err
   161  	}
   162  
   163  	var prop *protopeer.Proposal
   164  	if txid == "" {
   165  		// if txid is not set, then we need to generate one while creating the proposal message
   166  		prop, txid, err = protoutil.CreateChaincodeProposal(
   167  			headerType,
   168  			channelID,
   169  			&protopeer.ChaincodeInvocationSpec{
   170  				ChaincodeSpec: &protopeer.ChaincodeSpec{
   171  					ChaincodeId: ccid,
   172  				},
   173  			},
   174  			ss,
   175  		)
   176  
   177  	} else {
   178  		// if txid is set, we should not generate a txid instead reuse the given txid
   179  		nonce, err := crypto.GetRandomNonce()
   180  		if err != nil {
   181  			return nil, "", err
   182  		}
   183  		prop, txid, err = protoutil.CreateChaincodeProposalWithTxIDNonceAndTransient(
   184  			txid,
   185  			headerType,
   186  			channelID,
   187  			&protopeer.ChaincodeInvocationSpec{
   188  				ChaincodeSpec: &protopeer.ChaincodeSpec{
   189  					ChaincodeId: ccid,
   190  				},
   191  			},
   192  			nonce,
   193  			ss,
   194  			nil,
   195  		)
   196  	}
   197  	if err != nil {
   198  		return nil, "", err
   199  	}
   200  
   201  	presp, err := protoutil.CreateProposalResponse(
   202  		prop.Header,
   203  		prop.Payload,
   204  		response,
   205  		simulationResults,
   206  		nil,
   207  		ccid,
   208  		sigID,
   209  	)
   210  	if err != nil {
   211  		return nil, "", err
   212  	}
   213  
   214  	env, err := protoutil.CreateSignedTx(prop, sigID, presp)
   215  	if err != nil {
   216  		return nil, "", err
   217  	}
   218  	return env, txid, nil
   219  }
   220  
   221  func constructTestGenesisBlock(channelid string) (*common.Block, error) {
   222  	blk, err := configtxtest.MakeGenesisBlock(channelid)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	setBlockFlagsToValid(blk)
   227  	return blk, nil
   228  }
   229  
   230  func setBlockFlagsToValid(block *common.Block) {
   231  	protoutil.InitBlockMetadata(block)
   232  	block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] =
   233  		lutils.NewTxValidationFlagsSetValue(len(block.Data.Data), protopeer.TxValidationCode_VALID)
   234  }
   235  
   236  func couchDBSetup(t *testing.T, couchdbMountDir string, localdHostDir string) (addr string, cleanup func()) {
   237  	couchDB := &runner.CouchDB{
   238  		Name: "ledger13_upgrade_test",
   239  		Binds: []string{
   240  			fmt.Sprintf("%s:%s", couchdbMountDir, "/opt/couchdb/data"),
   241  			fmt.Sprintf("%s:%s", localdHostDir, "/opt/couchdb/etc/local.d"),
   242  		},
   243  	}
   244  	err := couchDB.Start()
   245  	require.NoError(t, err)
   246  	return couchDB.Address(), func() {
   247  		couchDB.Stop()
   248  	}
   249  }
   250  
   251  func dropCouchDBs(t *testing.T, couchdbConfig *couchdb.Config) {
   252  	couchInstance, err := couchdb.CreateCouchInstance(couchdbConfig, &disabled.Provider{})
   253  	require.NoError(t, err)
   254  	dbNames, err := couchInstance.RetrieveApplicationDBNames()
   255  	require.NoError(t, err)
   256  	for _, dbName := range dbNames {
   257  		db := &couchdb.CouchDatabase{
   258  			CouchInstance: couchInstance,
   259  			DBName:        dbName,
   260  		}
   261  		response, err := db.DropDatabase()
   262  		require.NoError(t, err)
   263  		require.True(t, response.Ok)
   264  	}
   265  }