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 }