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