github.com/true-sqn/fabric@v2.1.1+incompatible/core/chaincode/chaincode_support_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode 8 9 import ( 10 "archive/tar" 11 "bytes" 12 "compress/gzip" 13 "errors" 14 "flag" 15 "fmt" 16 "io/ioutil" 17 "os" 18 "path/filepath" 19 "strings" 20 "sync" 21 "testing" 22 "time" 23 24 docker "github.com/fsouza/go-dockerclient" 25 "github.com/golang/protobuf/proto" 26 "github.com/hyperledger/fabric-chaincode-go/shim" 27 "github.com/hyperledger/fabric-protos-go/common" 28 plgr "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 29 pb "github.com/hyperledger/fabric-protos-go/peer" 30 "github.com/hyperledger/fabric/bccsp/factory" 31 "github.com/hyperledger/fabric/bccsp/sw" 32 "github.com/hyperledger/fabric/common/crypto/tlsgen" 33 "github.com/hyperledger/fabric/common/flogging" 34 commonledger "github.com/hyperledger/fabric/common/ledger" 35 "github.com/hyperledger/fabric/common/metrics/disabled" 36 "github.com/hyperledger/fabric/common/policies" 37 "github.com/hyperledger/fabric/common/util" 38 "github.com/hyperledger/fabric/core/aclmgmt/resources" 39 "github.com/hyperledger/fabric/core/chaincode/accesscontrol" 40 "github.com/hyperledger/fabric/core/chaincode/lifecycle" 41 "github.com/hyperledger/fabric/core/chaincode/mock" 42 "github.com/hyperledger/fabric/core/chaincode/persistence" 43 "github.com/hyperledger/fabric/core/chaincode/platforms" 44 "github.com/hyperledger/fabric/core/chaincode/platforms/golang" 45 "github.com/hyperledger/fabric/core/common/ccprovider" 46 "github.com/hyperledger/fabric/core/config" 47 "github.com/hyperledger/fabric/core/container" 48 "github.com/hyperledger/fabric/core/container/ccintf" 49 "github.com/hyperledger/fabric/core/container/dockercontroller" 50 "github.com/hyperledger/fabric/core/ledger" 51 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 52 "github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest" 53 ledgermock "github.com/hyperledger/fabric/core/ledger/mock" 54 cut "github.com/hyperledger/fabric/core/ledger/util" 55 "github.com/hyperledger/fabric/core/peer" 56 "github.com/hyperledger/fabric/core/policy" 57 policymocks "github.com/hyperledger/fabric/core/policy/mocks" 58 "github.com/hyperledger/fabric/core/scc" 59 "github.com/hyperledger/fabric/core/scc/lscc" 60 "github.com/hyperledger/fabric/msp" 61 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 62 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 63 "github.com/hyperledger/fabric/protoutil" 64 "github.com/spf13/viper" 65 "github.com/stretchr/testify/assert" 66 ) 67 68 // CCContext is a legacy structure that was utilized heavily in the tests 69 // so it has been preserved, even though it basically passes a name/version pair 70 // alone. 71 type CCContext struct { 72 Name string 73 Version string 74 } 75 76 var globalBlockNum map[string]uint64 77 78 type mockResultsIterator struct { 79 current int 80 kvs []*plgr.KV 81 } 82 83 func (mri *mockResultsIterator) Next() (commonledger.QueryResult, error) { 84 if mri.current == len(mri.kvs) { 85 return nil, nil 86 } 87 kv := mri.kvs[mri.current] 88 mri.current = mri.current + 1 89 90 return kv, nil 91 } 92 93 func (mri *mockResultsIterator) Close() { 94 mri.current = len(mri.kvs) 95 } 96 97 type mockExecQuerySimulator struct { 98 txsim ledger.TxSimulator 99 resultsIter map[string]map[string]*mockResultsIterator 100 } 101 102 func (meqe *mockExecQuerySimulator) GetHistoryForKey(namespace, query string) (commonledger.ResultsIterator, error) { 103 return meqe.commonQuery(namespace, query) 104 } 105 106 func (meqe *mockExecQuerySimulator) ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) { 107 return meqe.commonQuery(namespace, query) 108 } 109 110 func (meqe *mockExecQuerySimulator) commonQuery(namespace, query string) (commonledger.ResultsIterator, error) { 111 if meqe.resultsIter == nil { 112 return nil, fmt.Errorf("query executor not initialized") 113 } 114 nsiter := meqe.resultsIter[namespace] 115 if nsiter == nil { 116 return nil, fmt.Errorf("namespace %v not found for %s", namespace, query) 117 } 118 iter := nsiter[query] 119 if iter == nil { 120 fmt.Printf("iter not found for query %s\n", query) 121 } 122 return iter, nil 123 } 124 125 func (meqe *mockExecQuerySimulator) SetState(namespace string, key string, value []byte) error { 126 if meqe.txsim == nil { 127 return fmt.Errorf("SetState txsimulator not initialed") 128 } 129 return meqe.txsim.SetState(namespace, key, value) 130 } 131 132 func (meqe *mockExecQuerySimulator) DeleteState(namespace string, key string) error { 133 if meqe.txsim == nil { 134 return fmt.Errorf("SetState txsimulator not initialed") 135 } 136 return meqe.txsim.DeleteState(namespace, key) 137 } 138 139 func (meqe *mockExecQuerySimulator) SetStateMultipleKeys(namespace string, kvs map[string][]byte) error { 140 if meqe.txsim == nil { 141 return fmt.Errorf("SetState txsimulator not initialed") 142 } 143 return meqe.txsim.SetStateMultipleKeys(namespace, kvs) 144 } 145 146 func (meqe *mockExecQuerySimulator) ExecuteUpdate(query string) error { 147 if meqe.txsim == nil { 148 return fmt.Errorf("SetState txsimulator not initialed") 149 } 150 return meqe.txsim.ExecuteUpdate(query) 151 } 152 153 func (meqe *mockExecQuerySimulator) GetTxSimulationResults() ([]byte, error) { 154 if meqe.txsim == nil { 155 return nil, fmt.Errorf("SetState txsimulator not initialed") 156 } 157 simRes, err := meqe.txsim.GetTxSimulationResults() 158 if err != nil { 159 return nil, err 160 } 161 return simRes.GetPubSimulationBytes() 162 } 163 164 //initialize peer and start up. If security==enabled, login as vp 165 func initMockPeer(channelIDs ...string) (*peer.Peer, *ChaincodeSupport, func(), error) { 166 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 167 if err != nil { 168 panic(fmt.Sprintf("failed to create cryptoProvider: %s", err)) 169 } 170 171 peerInstance := &peer.Peer{CryptoProvider: cryptoProvider} 172 173 tempdir, err := ioutil.TempDir("", "cc-support-test") 174 if err != nil { 175 panic(fmt.Sprintf("failed to create temporary directory: %s", err)) 176 } 177 178 initializer := ledgermgmttest.NewInitializer(filepath.Join(tempdir, "ledgerData")) 179 peerInstance.LedgerMgr = ledgermgmt.NewLedgerMgr(initializer) 180 181 cleanup := func() { 182 peerInstance.LedgerMgr.Close() 183 os.RemoveAll(tempdir) 184 } 185 186 mockAclProvider := &mock.ACLProvider{} 187 ccprovider.SetChaincodesPath(tempdir) 188 ca, _ := tlsgen.NewCA() 189 certGenerator := accesscontrol.NewAuthenticator(ca) 190 globalConfig := GlobalConfig() 191 globalConfig.ExecuteTimeout = 1 * time.Second 192 globalConfig.InstallTimeout = 90 * time.Second 193 globalConfig.StartupTimeout = 10 * time.Second 194 195 buildRegistry := &container.BuildRegistry{} 196 197 client, err := docker.NewClientFromEnv() 198 if err != nil { 199 panic(err) 200 } 201 202 containerRouter := &container.Router{ 203 DockerBuilder: &dockercontroller.DockerVM{ 204 PlatformBuilder: &platforms.Builder{ 205 Registry: platforms.NewRegistry(&golang.Platform{}), 206 Client: client, 207 }, 208 }, 209 PackageProvider: &persistence.FallbackPackageLocator{ 210 ChaincodePackageLocator: &persistence.ChaincodePackageLocator{}, 211 LegacyCCPackageLocator: &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider}, 212 }, 213 } 214 215 lsccImpl := &lscc.SCC{ 216 BuiltinSCCs: map[string]struct{}{"lscc": {}}, 217 Support: &lscc.SupportImpl{ 218 GetMSPIDs: peerInstance.GetMSPIDs, 219 }, 220 SCCProvider: &lscc.PeerShim{Peer: peerInstance}, 221 ACLProvider: mockAclProvider, 222 GetMSPIDs: peerInstance.GetMSPIDs, 223 PolicyChecker: newPolicyChecker(peerInstance), 224 BCCSP: cryptoProvider, 225 BuildRegistry: buildRegistry, 226 ChaincodeBuilder: containerRouter, 227 } 228 229 ml := &mock.Lifecycle{} 230 ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) { 231 switch name { 232 case "shimTestCC", "calledCC": 233 return &lifecycle.ChaincodeEndorsementInfo{ 234 ChaincodeID: name + ":0", 235 }, nil 236 case "lscc": 237 return &lifecycle.ChaincodeEndorsementInfo{ 238 ChaincodeID: "lscc.syscc", 239 }, nil 240 default: 241 return nil, errors.New("oh-bother-no-chaincode-info") 242 } 243 } 244 245 containerRuntime := &ContainerRuntime{ 246 BuildRegistry: buildRegistry, 247 ContainerRouter: containerRouter, 248 } 249 userRunsCC := true 250 metricsProviders := &disabled.Provider{} 251 chaincodeHandlerRegistry := NewHandlerRegistry(userRunsCC) 252 chaincodeLauncher := &RuntimeLauncher{ 253 Metrics: NewLaunchMetrics(metricsProviders), 254 Runtime: containerRuntime, 255 Registry: chaincodeHandlerRegistry, 256 StartupTimeout: globalConfig.StartupTimeout, 257 CACert: ca.CertBytes(), 258 CertGenerator: certGenerator, 259 } 260 if !globalConfig.TLSEnabled { 261 chaincodeLauncher.CertGenerator = nil 262 } 263 chaincodeSupport := &ChaincodeSupport{ 264 ACLProvider: mockAclProvider, 265 AppConfig: peerInstance, 266 DeployedCCInfoProvider: &ledgermock.DeployedChaincodeInfoProvider{}, 267 ExecuteTimeout: globalConfig.ExecuteTimeout, 268 InstallTimeout: globalConfig.InstallTimeout, 269 HandlerMetrics: NewHandlerMetrics(metricsProviders), 270 HandlerRegistry: chaincodeHandlerRegistry, 271 Keepalive: globalConfig.Keepalive, 272 Launcher: chaincodeLauncher, 273 Lifecycle: ml, 274 Peer: peerInstance, 275 Runtime: containerRuntime, 276 BuiltinSCCs: map[string]struct{}{"lscc": {}}, 277 TotalQueryLimit: globalConfig.TotalQueryLimit, 278 UserRunsCC: userRunsCC, 279 } 280 281 scc.DeploySysCC(lsccImpl, chaincodeSupport) 282 283 globalBlockNum = make(map[string]uint64, len(channelIDs)) 284 for _, id := range channelIDs { 285 capabilities := &mock.ApplicationCapabilities{} 286 config := &mock.ApplicationConfig{} 287 config.CapabilitiesReturns(capabilities) 288 resources := &mock.Resources{} 289 resources.ApplicationConfigReturns(config, true) 290 if err := peer.CreateMockChannel(peerInstance, id, resources); err != nil { 291 cleanup() 292 return nil, nil, func() {}, err 293 } 294 295 // any channel other than the default testchannelid does not have a MSP set up -> create one 296 if id != "testchannelid" { 297 mspmgmt.XXXSetMSPManager(id, mspmgmt.GetManagerForChain("testchannelid")) 298 } 299 globalBlockNum[id] = 1 300 } 301 302 return peerInstance, chaincodeSupport, cleanup, nil 303 } 304 305 func finitMockPeer(peerInstance *peer.Peer, channelIDs ...string) { 306 for _, c := range channelIDs { 307 if lgr := peerInstance.GetLedger(c); lgr != nil { 308 lgr.Close() 309 } 310 } 311 ledgerPath := config.GetPath("peer.fileSystemPath") 312 os.RemoveAll(ledgerPath) 313 os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger")) 314 } 315 316 //store the stream CC mappings here 317 var mockPeerCCSupport = mock.NewMockPeerSupport() 318 319 func setupcc(name string) (*mock.MockCCComm, *mock.MockCCComm) { 320 send := make(chan *pb.ChaincodeMessage) 321 recv := make(chan *pb.ChaincodeMessage) 322 peerSide, _ := mockPeerCCSupport.AddCC(name, recv, send) 323 peerSide.SetName("peer") 324 ccSide := mockPeerCCSupport.GetCCMirror(name) 325 ccSide.SetPong(true) 326 return peerSide, ccSide 327 } 328 329 //assign this to done and failNow and keep using them 330 func setuperror() chan error { 331 return make(chan error) 332 } 333 334 func processDone(t *testing.T, done chan error, expecterr bool) { 335 var err error 336 if done != nil { 337 err = <-done 338 } 339 if expecterr != (err != nil) { 340 if err == nil { 341 t.Fatalf("Expected error but got success") 342 } else { 343 t.Fatalf("Expected success but got error %s", err) 344 } 345 } 346 } 347 348 func startTx(t *testing.T, peerInstance *peer.Peer, channelID string, cis *pb.ChaincodeInvocationSpec, txId string) (*ccprovider.TransactionParams, ledger.TxSimulator) { 349 creator := []byte([]byte("Alice")) 350 sprop, prop := protoutil.MockSignedEndorserProposalOrPanic(channelID, cis.ChaincodeSpec, creator, []byte("msg1")) 351 txsim, hqe, err := startTxSimulation(peerInstance, channelID, txId) 352 if err != nil { 353 t.Fatalf("getting txsimulator failed %s", err) 354 } 355 356 txParams := &ccprovider.TransactionParams{ 357 ChannelID: channelID, 358 TxID: txId, 359 Proposal: prop, 360 SignedProp: sprop, 361 TXSimulator: txsim, 362 HistoryQueryExecutor: hqe, 363 } 364 365 return txParams, txsim 366 } 367 368 func endTx(t *testing.T, peerInstance *peer.Peer, txParams *ccprovider.TransactionParams, txsim ledger.TxSimulator, cis *pb.ChaincodeInvocationSpec) { 369 if err := endTxSimulationCIS(peerInstance, txParams.ChannelID, cis.ChaincodeSpec.ChaincodeId, txParams.TxID, txsim, []byte("invoke"), true, cis, globalBlockNum[txParams.ChannelID]); err != nil { 370 t.Fatalf("simulation failed with error %s", err) 371 } 372 globalBlockNum[txParams.ChannelID] = globalBlockNum[txParams.ChannelID] + 1 373 } 374 375 func execCC(t *testing.T, txParams *ccprovider.TransactionParams, ccSide *mock.MockCCComm, chaincodeName string, waitForERROR bool, expectExecErr bool, done chan error, cis *pb.ChaincodeInvocationSpec, respSet *mock.MockResponseSet, chaincodeSupport *ChaincodeSupport) error { 376 ccSide.SetResponses(respSet) 377 378 resp, _, err := chaincodeSupport.Execute(txParams, chaincodeName, cis.ChaincodeSpec.Input) 379 if err == nil && resp.Status != shim.OK { 380 err = errors.New(resp.Message) 381 } 382 383 if err == nil && expectExecErr { 384 t.Fatalf("expected error but succeeded") 385 } else if err != nil && !expectExecErr { 386 t.Fatalf("exec failed with %s", err) 387 } 388 389 //wait 390 processDone(t, done, waitForERROR) 391 392 return nil 393 } 394 395 //initialize cc support env and startup the chaincode 396 func startCC(t *testing.T, channelID string, ccname string, chaincodeSupport *ChaincodeSupport) (*mock.MockCCComm, *mock.MockCCComm) { 397 peerSide, ccSide := setupcc(ccname) 398 defer mockPeerCCSupport.RemoveCC(ccname) 399 400 //register peer side with ccsupport 401 go func() { 402 chaincodeSupport.HandleChaincodeStream(peerSide) 403 }() 404 405 done := setuperror() 406 407 errorFunc := func(ind int, err error) { 408 done <- err 409 } 410 411 ccDone := make(chan struct{}) 412 defer close(ccDone) 413 414 //start the mock peer 415 go func() { 416 respSet := &mock.MockResponseSet{ 417 DoneFunc: errorFunc, 418 ErrorFunc: nil, 419 Responses: []*mock.MockResponse{ 420 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}, RespMsg: nil}, 421 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY}, RespMsg: nil}, 422 }, 423 } 424 ccSide.SetResponses(respSet) 425 ccSide.Run(ccDone) 426 }() 427 428 ccSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeID{Name: ccname + ":0"}), Txid: "0", ChannelId: channelID}) 429 430 //wait for init 431 processDone(t, done, false) 432 433 return peerSide, ccSide 434 } 435 436 func getTarGZ(t *testing.T, name string, contents []byte) []byte { 437 startTime := time.Now() 438 inputbuf := bytes.NewBuffer(nil) 439 gw := gzip.NewWriter(inputbuf) 440 tr := tar.NewWriter(gw) 441 size := int64(len(contents)) 442 443 tr.WriteHeader(&tar.Header{Name: name, Size: size, ModTime: startTime, AccessTime: startTime, ChangeTime: startTime}) 444 tr.Write(contents) 445 tr.Close() 446 gw.Close() 447 ioutil.WriteFile("/tmp/t.gz", inputbuf.Bytes(), 0644) 448 return inputbuf.Bytes() 449 } 450 451 // Deploy a chaincode - i.e., build and initialize. 452 func deployCC(t *testing.T, txParams *ccprovider.TransactionParams, ccContext *CCContext, spec *pb.ChaincodeSpec, chaincodeSupport *ChaincodeSupport) { 453 // First build and get the deployment spec 454 code := getTarGZ(t, "src/dummy/dummy.go", []byte("code")) 455 cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: code} 456 457 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 458 assert.NoError(t, err) 459 ccinfoFSImpl := &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider} 460 _, err = ccinfoFSImpl.PutChaincode(cds) 461 assert.NoError(t, err) 462 463 b := protoutil.MarshalOrPanic(cds) 464 465 //wrap the deployment in an invocation spec to lscc... 466 lsccSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: "lscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("deploy"), []byte(txParams.ChannelID), b}}}} 467 468 //write to lscc 469 if _, _, err := chaincodeSupport.Execute(txParams, "lscc", lsccSpec.ChaincodeSpec.Input); err != nil { 470 t.Fatalf("Error deploying chaincode %v (err: %s)", ccContext, err) 471 } 472 } 473 474 func initializeCC(t *testing.T, chainID, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 475 done := setuperror() 476 477 errorFunc := func(ind int, err error) { 478 done <- err 479 } 480 481 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 482 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}, Decorations: nil} 483 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 484 485 txid := util.GenerateUUID() 486 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 487 488 //bad txid in response (should be "1"), should fail 489 resp := &mock.MockResponse{ 490 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, 491 RespMsg: &pb.ChaincodeMessage{ 492 Type: pb.ChaincodeMessage_COMPLETED, 493 Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}), 494 Txid: "unknowntxid", 495 ChannelId: chainID, 496 }, 497 } 498 respSet := &mock.MockResponseSet{ 499 DoneFunc: errorFunc, 500 ErrorFunc: nil, 501 Responses: []*mock.MockResponse{resp}, 502 } 503 504 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 505 506 //set the right TxID in response now 507 resp = &mock.MockResponse{ 508 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, 509 RespMsg: &pb.ChaincodeMessage{ 510 Type: pb.ChaincodeMessage_COMPLETED, 511 Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("init succeeded")}), 512 Txid: txid, 513 ChannelId: chainID, 514 }, 515 } 516 respSet = &mock.MockResponseSet{ 517 DoneFunc: errorFunc, 518 ErrorFunc: nil, 519 Responses: []*mock.MockResponse{resp}, 520 } 521 522 //we are not going to reach the chaincode and so won't get a response from it. processDone will not 523 //be triggered by the chaincode stream. We just expect an error from fabric. Hence pass nil for done 524 execCC(t, txParams, ccSide, "badccname", false, true, nil, cis, respSet, chaincodeSupport) 525 526 //---------try a successful init at last------- 527 //everything lined up 528 // correct registered chaincode version 529 // matching txid 530 // txsim context 531 // full response 532 // correct block number for ending sim 533 534 respSet = &mock.MockResponseSet{ 535 DoneFunc: errorFunc, 536 ErrorFunc: nil, 537 Responses: []*mock.MockResponse{ 538 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("100")}), Txid: txid, ChannelId: chainID}}, 539 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("200")}), Txid: txid, ChannelId: chainID}}, 540 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), ChaincodeEvent: &pb.ChaincodeEvent{ChaincodeId: ccname}, Txid: txid, ChannelId: chainID}}, 541 }, 542 } 543 544 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 545 546 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 547 548 return nil 549 } 550 551 func invokeCC(t *testing.T, chainID, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 552 done := setuperror() 553 554 errorFunc := func(ind int, err error) { 555 done <- err 556 } 557 558 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 559 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} 560 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 561 txid := util.GenerateUUID() 562 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 563 564 respSet := &mock.MockResponseSet{ 565 DoneFunc: errorFunc, 566 ErrorFunc: nil, 567 Responses: []*mock.MockResponse{ 568 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "A"}), Txid: txid, ChannelId: chainID}}, 569 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "B"}), Txid: txid, ChannelId: chainID}}, 570 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "A", Value: []byte("90")}), Txid: txid, ChannelId: chainID}}, 571 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "B", Value: []byte("210")}), Txid: txid, ChannelId: chainID}}, 572 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Payload: protoutil.MarshalOrPanic(&pb.PutState{Collection: "", Key: "TODEL", Value: []byte("-to-be-deleted-")}), Txid: txid, ChannelId: chainID}}, 573 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}, 574 }, 575 } 576 577 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 578 579 //delete the extra var 580 respSet = &mock.MockResponseSet{ 581 DoneFunc: errorFunc, 582 ErrorFunc: nil, 583 Responses: []*mock.MockResponse{ 584 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}}, 585 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Payload: protoutil.MarshalOrPanic(&pb.DelState{Collection: "", Key: "TODEL"}), Txid: "3", ChannelId: chainID}}, 586 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: "3", ChannelId: chainID}}, 587 }, 588 } 589 590 txParams.TxID = "3" 591 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 592 593 //get the extra var and delete it 594 respSet = &mock.MockResponseSet{ 595 DoneFunc: errorFunc, 596 ErrorFunc: nil, 597 Responses: []*mock.MockResponse{ 598 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Payload: protoutil.MarshalOrPanic(&pb.GetState{Collection: "", Key: "TODEL"}), Txid: "4", ChannelId: chainID}}, 599 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "variable not found"}), Txid: "4", ChannelId: chainID}}, 600 }, 601 } 602 603 txParams.TxID = "4" 604 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 605 606 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 607 608 return nil 609 } 610 611 func getQueryStateByRange(t *testing.T, collection, chainID, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 612 done := setuperror() 613 errorFunc := func(ind int, err error) { 614 done <- err 615 } 616 617 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 618 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} 619 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 620 txid := util.GenerateUUID() 621 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 622 623 //create the response 624 queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 625 qr := &pb.QueryResponse{} 626 proto.Unmarshal(reqMsg.Payload, qr) 627 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID} 628 } 629 queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 630 qr := &pb.QueryResponse{} 631 proto.Unmarshal(reqMsg.Payload, qr) 632 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID} 633 } 634 635 var mkpeer []*mock.MockResponse 636 637 mkpeer = append(mkpeer, &mock.MockResponse{ 638 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, 639 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Payload: protoutil.MarshalOrPanic(&pb.GetStateByRange{Collection: collection, StartKey: "A", EndKey: "B"}), Txid: txid, ChannelId: chainID}, 640 }) 641 642 if collection == "" { 643 mkpeer = append(mkpeer, &mock.MockResponse{ 644 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, 645 RespMsg: queryStateNextFunc, 646 }) 647 mkpeer = append(mkpeer, &mock.MockResponse{ 648 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, 649 RespMsg: queryStateCloseFunc, 650 }) 651 mkpeer = append(mkpeer, &mock.MockResponse{ 652 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, 653 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}, 654 }) 655 } else { 656 // Range queries on private data is not yet implemented. 657 mkpeer = append(mkpeer, &mock.MockResponse{ 658 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, 659 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID}, 660 }) 661 } 662 663 respSet := &mock.MockResponseSet{ 664 DoneFunc: errorFunc, 665 ErrorFunc: nil, 666 Responses: mkpeer, 667 } 668 669 if collection == "" { 670 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 671 } else { 672 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 673 } 674 675 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 676 677 return nil 678 } 679 680 func cc2cc(t *testing.T, chainID, chainID2, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 681 calledCC := "calledCC" 682 //starts and registers the CC 683 _, calledCCSide := startCC(t, chainID2, calledCC, chaincodeSupport) 684 if calledCCSide == nil { 685 t.Fatalf("start up failed for called CC") 686 } 687 defer calledCCSide.Quit() 688 689 done := setuperror() 690 691 errorFunc := func(ind int, err error) { 692 done <- err 693 } 694 695 chaincodeID := &pb.ChaincodeID{Name: calledCC, Version: "0"} 696 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil} 697 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 698 txid := util.GenerateUUID() 699 //first deploy the new cc to LSCC 700 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 701 702 ccContext := &CCContext{ 703 Name: calledCC, 704 Version: "0", 705 } 706 707 deployCC(t, txParams, ccContext, cis.ChaincodeSpec, chaincodeSupport) 708 709 //commit 710 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 711 712 //now do the cc2cc 713 chaincodeID = &pb.ChaincodeID{Name: ccname, Version: "0"} 714 ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invokecc")}, Decorations: nil} 715 cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 716 txid = util.GenerateUUID() 717 txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 718 719 //call a callable system CC, a regular cc, a regular but different cc on a different chain, a regular but same cc on a different chain, and an uncallable system cc and expect an error inthe last one 720 respSet := &mock.MockResponseSet{ 721 DoneFunc: errorFunc, 722 ErrorFunc: nil, 723 Responses: []*mock.MockResponse{ 724 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "lscc.syscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 725 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 726 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 727 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "vscc.syscc"}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 728 }, 729 } 730 731 respSet2 := &mock.MockResponseSet{ 732 DoneFunc: nil, 733 ErrorFunc: nil, 734 Responses: []*mock.MockResponse{ 735 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}, 736 }, 737 } 738 calledCCSide.SetResponses(respSet2) 739 740 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 741 742 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 743 744 //finally lets try a Bad ACL with CC-calling-CC 745 chaincodeID = &pb.ChaincodeID{Name: ccname, Version: "0"} 746 ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invokecc")}, Decorations: nil} 747 cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 748 txid = util.GenerateUUID() 749 txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 750 751 mockAclProvider := chaincodeSupport.ACLProvider.(*mock.ACLProvider) 752 mockAclProvider.CheckACLStub = func(resource, channel string, _ interface{}) error { 753 if resource == resources.Peer_ChaincodeToChaincode && channel == chainID { 754 return errors.New("bad-acl-calling-cc") 755 } 756 return nil 757 } 758 759 //call regular cc but without ACL on called CC 760 respSet = &mock.MockResponseSet{ 761 DoneFunc: errorFunc, 762 ErrorFunc: nil, 763 Responses: []*mock.MockResponse{ 764 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: "calledCC:0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 765 }, 766 } 767 768 respSet2 = &mock.MockResponseSet{ 769 DoneFunc: nil, 770 ErrorFunc: nil, 771 Responses: []*mock.MockResponse{ 772 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}, 773 }, 774 } 775 776 calledCCSide.SetResponses(respSet2) 777 778 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 779 780 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 781 782 return nil 783 } 784 785 func getQueryResult(t *testing.T, collection, chainID, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 786 done := setuperror() 787 788 errorFunc := func(ind int, err error) { 789 done <- err 790 } 791 792 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 793 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} 794 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 795 txid := util.GenerateUUID() 796 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 797 798 kvs := make([]*plgr.KV, 1000) 799 for i := 0; i < 1000; i++ { 800 kvs[i] = &plgr.KV{Namespace: chainID, Key: fmt.Sprintf("%d", i), Value: []byte(fmt.Sprintf("%d", i))} 801 } 802 803 queryExec := &mockExecQuerySimulator{resultsIter: make(map[string]map[string]*mockResultsIterator)} 804 queryExec.resultsIter[ccname] = map[string]*mockResultsIterator{"goodquery": {kvs: kvs}} 805 806 queryExec.txsim = txParams.TXSimulator 807 808 //create the response 809 queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 810 qr := &pb.QueryResponse{} 811 proto.Unmarshal(reqMsg.Payload, qr) 812 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid, ChannelId: chainID} 813 } 814 queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 815 qr := &pb.QueryResponse{} 816 proto.Unmarshal(reqMsg.Payload, qr) 817 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid, ChannelId: chainID} 818 } 819 820 var mkpeer []*mock.MockResponse 821 822 mkpeer = append(mkpeer, &mock.MockResponse{ 823 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, 824 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Payload: protoutil.MarshalOrPanic(&pb.GetQueryResult{Collection: "", Query: "goodquery"}), Txid: txid, ChannelId: chainID}, 825 }) 826 827 if collection == "" { 828 mkpeer = append(mkpeer, &mock.MockResponse{ 829 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, 830 RespMsg: queryStateNextFunc, 831 }) 832 mkpeer = append(mkpeer, &mock.MockResponse{ 833 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, 834 RespMsg: queryStateCloseFunc, 835 }) 836 mkpeer = append(mkpeer, &mock.MockResponse{ 837 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, 838 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}, 839 }) 840 } else { 841 // Get query results on private data is not yet implemented. 842 mkpeer = append(mkpeer, &mock.MockResponse{ 843 RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, 844 RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.ERROR, Message: "Not Yet Supported"}), Txid: txid, ChannelId: chainID}, 845 }) 846 } 847 848 respSet := &mock.MockResponseSet{ 849 DoneFunc: errorFunc, 850 ErrorFunc: nil, 851 Responses: mkpeer, 852 } 853 854 if collection == "" { 855 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 856 } else { 857 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 858 } 859 860 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 861 862 return nil 863 } 864 865 func getHistory(t *testing.T, chainID, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) error { 866 done := setuperror() 867 868 errorFunc := func(ind int, err error) { 869 done <- err 870 } 871 872 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 873 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} 874 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 875 txid := util.GenerateUUID() 876 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 877 878 kvs := make([]*plgr.KV, 1000) 879 for i := 0; i < 1000; i++ { 880 kvs[i] = &plgr.KV{Namespace: chainID, Key: fmt.Sprintf("%d", i), Value: []byte(fmt.Sprintf("%d", i))} 881 } 882 883 queryExec := &mockExecQuerySimulator{resultsIter: make(map[string]map[string]*mockResultsIterator)} 884 queryExec.resultsIter[ccname] = map[string]*mockResultsIterator{"goodquery": {kvs: kvs}} 885 886 queryExec.txsim = txParams.TXSimulator 887 888 //create the response 889 queryStateNextFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 890 qr := &pb.QueryResponse{} 891 proto.Unmarshal(reqMsg.Payload, qr) 892 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: protoutil.MarshalOrPanic(&pb.QueryStateNext{Id: qr.Id}), Txid: txid} 893 } 894 queryStateCloseFunc := func(reqMsg *pb.ChaincodeMessage) *pb.ChaincodeMessage { 895 qr := &pb.QueryResponse{} 896 proto.Unmarshal(reqMsg.Payload, qr) 897 return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: protoutil.MarshalOrPanic(&pb.QueryStateClose{Id: qr.Id}), Txid: txid} 898 } 899 900 respSet := &mock.MockResponseSet{ 901 DoneFunc: errorFunc, 902 ErrorFunc: nil, 903 Responses: []*mock.MockResponse{ 904 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Payload: protoutil.MarshalOrPanic(&pb.GetQueryResult{Query: "goodquery"}), Txid: txid, ChannelId: chainID}}, 905 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: queryStateNextFunc}, 906 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: queryStateNextFunc}, 907 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR}, RespMsg: queryStateCloseFunc}, 908 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: protoutil.MarshalOrPanic(&pb.Response{Status: shim.OK, Payload: []byte("OK")}), Txid: txid, ChannelId: chainID}}, 909 }, 910 } 911 912 execCC(t, txParams, ccSide, ccname, false, false, done, cis, respSet, chaincodeSupport) 913 914 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 915 916 return nil 917 } 918 919 //success case 920 func TestStartAndWaitSuccess(t *testing.T) { 921 handlerRegistry := NewHandlerRegistry(false) 922 fakeRuntime := &mock.Runtime{} 923 fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { 924 handlerRegistry.Ready("testcc:0") 925 return nil 926 } 927 928 launcher := &RuntimeLauncher{ 929 Runtime: fakeRuntime, 930 Registry: handlerRegistry, 931 StartupTimeout: 10 * time.Second, 932 Metrics: NewLaunchMetrics(&disabled.Provider{}), 933 } 934 935 fakeStreamHandler := &mock.ChaincodeStreamHandler{} 936 //actual test - everythings good 937 err := launcher.Launch("testcc:0", fakeStreamHandler) 938 if err != nil { 939 t.Fatalf("expected success but failed with error %s", err) 940 } 941 } 942 943 //test timeout error 944 func TestStartAndWaitTimeout(t *testing.T) { 945 fakeRuntime := &mock.Runtime{} 946 fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { 947 time.Sleep(time.Second) 948 return nil 949 } 950 951 launcher := &RuntimeLauncher{ 952 Runtime: fakeRuntime, 953 Registry: NewHandlerRegistry(false), 954 StartupTimeout: 500 * time.Millisecond, 955 Metrics: NewLaunchMetrics(&disabled.Provider{}), 956 } 957 958 fakeStreamHandler := &mock.ChaincodeStreamHandler{} 959 //the actual test - timeout 1000 > 500 960 err := launcher.Launch("testcc:0", fakeStreamHandler) 961 if err == nil { 962 t.Fatalf("expected error but succeeded") 963 } 964 } 965 966 //test container return error 967 func TestStartAndWaitLaunchError(t *testing.T) { 968 fakeRuntime := &mock.Runtime{} 969 fakeRuntime.StartStub = func(_ string, _ *ccintf.PeerConnection) error { 970 return errors.New("Bad lunch; upset stomach") 971 } 972 973 launcher := &RuntimeLauncher{ 974 Runtime: fakeRuntime, 975 Registry: NewHandlerRegistry(false), 976 StartupTimeout: 10 * time.Second, 977 Metrics: NewLaunchMetrics(&disabled.Provider{}), 978 } 979 980 fakeStreamHandler := &mock.ChaincodeStreamHandler{} 981 //actual test - container launch gives error 982 err := launcher.Launch("testcc:0", fakeStreamHandler) 983 if err == nil { 984 t.Fatalf("expected error but succeeded") 985 } 986 assert.EqualError(t, err, "error starting container: Bad lunch; upset stomach") 987 } 988 989 func TestGetTxContextFromHandler(t *testing.T) { 990 chnl := "test" 991 peerInstance, _, cleanup, err := initMockPeer(chnl) 992 assert.NoError(t, err, "failed to initialize mock peer") 993 defer cleanup() 994 995 h := Handler{ 996 TXContexts: NewTransactionContexts(), 997 BuiltinSCCs: map[string]struct{}{"lscc": {}}, 998 } 999 1000 txid := "1" 1001 // test getTxContext for TEST channel, tx=1, msgType=IVNOKE_CHAINCODE and empty payload - empty payload => expect to return empty txContext 1002 txContext, _ := h.getTxContextForInvoke(chnl, "1", []byte(""), "[%s]No ledger context for %s. Sending %s", 12345, "TestCC", pb.ChaincodeMessage_ERROR) 1003 assert.Nil(t, txContext, "expected empty txContext for empty payload") 1004 1005 pldgr := peerInstance.GetLedger(chnl) 1006 1007 // prepare a payload and generate a TxContext in the handler to be used in the following getTxContextFroMessage with a normal UCC 1008 txCtxGenerated, payload := genNewPldAndCtxFromLdgr(t, "shimTestCC", chnl, txid, pldgr, &h) 1009 1010 // test getTxContext for TEST channel, tx=1, msgType=IVNOKE_CHAINCODE and non empty payload => must return a non empty txContext 1011 txContext, ccMsg := h.getTxContextForInvoke(chnl, txid, payload, "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1012 if txContext == nil || ccMsg != nil || txContext != txCtxGenerated { 1013 t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg) 1014 } 1015 1016 // test for another msgType (PUT_STATE) with the same payload ==> must return a non empty txContext 1017 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_PUT_STATE, pb.ChaincodeMessage_ERROR) 1018 if txContext == nil || ccMsg != nil || txContext != txCtxGenerated { 1019 t.Fatalf("expected successful txContext for non empty payload and PUT_STATE msgType. triggerNextStateMsg: %s.", ccMsg) 1020 } 1021 1022 // get a new txContext for our SCC tests 1023 txid = "2" 1024 // reset channel to "" to test getting a context for an SCC without a channel 1025 chnl = "" 1026 txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "lscc", chnl, txid, pldgr, &h) 1027 1028 // test getting a TxContext with an SCC without a channel => expect to return a non empty txContext 1029 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, 1030 "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1031 if txContext == nil || ccMsg != nil || txContext != txCtxGenerated { 1032 t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg) 1033 } 1034 1035 // now reset back to non empty channel and test with an SCC 1036 txid = "3" 1037 chnl = "TEST" 1038 txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "lscc", chnl, txid, pldgr, &h) 1039 1040 // test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext 1041 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, 1042 "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1043 if txContext == nil || ccMsg != nil || txContext != txCtxGenerated { 1044 t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg) 1045 } 1046 1047 // now test getting a context with an empty channel and a UCC instead of an SCC 1048 txid = "4" 1049 chnl = "" 1050 txCtxGenerated, payload = genNewPldAndCtxFromLdgr(t, "shimTestCC", chnl, txid, pldgr, &h) 1051 // test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext 1052 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, 1053 "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1054 if txContext == nil || ccMsg != nil || txContext != txCtxGenerated { 1055 t.Fatalf("expected successful txContext for non empty payload and INVOKE_CHAINCODE msgType. triggerNextStateMsg: %s.", ccMsg) 1056 } 1057 1058 // new test getting a context with an empty channel without the ledger creating a new context for a UCC 1059 txid = "5" 1060 payload = genNewPld(t, "shimTestCC") 1061 // test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext 1062 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, 1063 "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1064 if txContext != nil || ccMsg == nil { 1065 t.Fatal("expected nil txContext for non empty payload and INVOKE_CHAINCODE msgType without the ledger generating a TxContext . unexpected non nil tcContext") 1066 } 1067 1068 // test same scenario as above but for an SCC this time 1069 txid = "6" 1070 payload = genNewPld(t, "lscc") 1071 // test getting a TxContext with an SCC with channel TEST => expect to return a non empty txContext 1072 txContext, ccMsg = h.getTxContextForInvoke(chnl, txid, payload, 1073 "[%s]No ledger context for %s. Sending %s", 12345, pb.ChaincodeMessage_INVOKE_CHAINCODE, pb.ChaincodeMessage_ERROR) 1074 if txContext != nil || ccMsg == nil { 1075 t.Fatal("expected nil txContext for non empty payload and INVOKE_CHAINCODE msgType without the ledger generating a TxContext . unexpected non nil tcContext") 1076 } 1077 } 1078 1079 func genNewPldAndCtxFromLdgr(t *testing.T, ccName string, chnl string, txid string, pldgr ledger.PeerLedger, h *Handler) (*TransactionContext, []byte) { 1080 // create a new TxSimulator for the received txid 1081 txsim, err := pldgr.NewTxSimulator(txid) 1082 if err != nil { 1083 t.Fatalf("failed to create TxSimulator %s", err) 1084 } 1085 txParams := &ccprovider.TransactionParams{ 1086 TxID: txid, 1087 ChannelID: chnl, 1088 TXSimulator: txsim, 1089 NamespaceID: ccName, 1090 } 1091 newTxCtxt, err := h.TXContexts.Create(txParams) 1092 if err != nil { 1093 t.Fatalf("Error creating TxContext by the handler for cc %s and channel '%s': %s", ccName, chnl, err) 1094 } 1095 if newTxCtxt == nil { 1096 t.Fatalf("Error creating TxContext: newTxCtxt created by the handler is nil for cc %s and channel '%s'.", ccName, chnl) 1097 } 1098 // build a new cds and payload for the CC called ccName 1099 payload := genNewPld(t, ccName) 1100 return newTxCtxt, payload 1101 } 1102 1103 func genNewPld(t *testing.T, ccName string) []byte { 1104 // build a new cds and payload for the CC called ccName 1105 chaincodeID := &pb.ChaincodeID{Name: ccName, Version: "0"} 1106 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil} 1107 cds := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci} 1108 payload, err := proto.Marshal(cds) 1109 if err != nil { 1110 t.Fatalf("failed to marshal CDS %s", err) 1111 } 1112 return payload 1113 } 1114 1115 func cc2SameCC(t *testing.T, chainID, chainID2, ccname string, ccSide *mock.MockCCComm, chaincodeSupport *ChaincodeSupport) { 1116 //first deploy the CC on chainID2 1117 chaincodeID := &pb.ChaincodeID{Name: ccname, Version: "0"} 1118 ci := &pb.ChaincodeInput{Args: [][]byte{[]byte("deploycc")}, Decorations: nil} 1119 cis := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 1120 1121 txid := util.GenerateUUID() 1122 txParams, txsim := startTx(t, chaincodeSupport.Peer, chainID2, cis, txid) 1123 1124 ccContext := &CCContext{ 1125 Name: ccname, 1126 Version: "0", 1127 } 1128 1129 deployCC(t, txParams, ccContext, cis.ChaincodeSpec, chaincodeSupport) 1130 1131 //commit 1132 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 1133 1134 done := setuperror() 1135 1136 errorFunc := func(ind int, err error) { 1137 done <- err 1138 } 1139 1140 //now for the test - call the same cc on a different channel(should succeed), call the same cc on the same channel(should fail) 1141 //Note the error "Another request pending for this Txid. Cannot process." in the logs under TX "cctosamecctx" 1142 ci = &pb.ChaincodeInput{Args: [][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}, Decorations: nil} 1143 cis = &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), ChaincodeId: chaincodeID, Input: ci}} 1144 txid = util.GenerateUUID() 1145 txParams, txsim = startTx(t, chaincodeSupport.Peer, chainID, cis, txid) 1146 1147 txid = "cctosamecctx" 1148 respSet := &mock.MockResponseSet{ 1149 DoneFunc: errorFunc, 1150 ErrorFunc: nil, 1151 Responses: []*mock.MockResponse{ 1152 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID2}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 1153 {RecvMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE}, RespMsg: &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Payload: protoutil.MarshalOrPanic(&pb.ChaincodeSpec{ChaincodeId: &pb.ChaincodeID{Name: ccname + ":0/" + chainID}, Input: &pb.ChaincodeInput{Args: [][]byte{{}}}}), Txid: txid, ChannelId: chainID}}, 1154 }, 1155 } 1156 1157 execCC(t, txParams, ccSide, ccname, false, true, done, cis, respSet, chaincodeSupport) 1158 1159 endTx(t, chaincodeSupport.Peer, txParams, txsim, cis) 1160 } 1161 1162 func TestCCFramework(t *testing.T) { 1163 //register 2 channels 1164 chainID := "mockchainid" 1165 chainID2 := "secondchain" 1166 peerInstance, chaincodeSupport, cleanup, err := initMockPeer(chainID, chainID2) 1167 if err != nil { 1168 t.Fatalf("%s", err) 1169 } 1170 defer cleanup() 1171 defer finitMockPeer(peerInstance, chainID, chainID2) 1172 //create a chaincode 1173 ccname := "shimTestCC" 1174 1175 //starts and registers the CC 1176 _, ccSide := startCC(t, chainID, ccname, chaincodeSupport) 1177 if ccSide == nil { 1178 t.Fatalf("start up failed") 1179 } 1180 defer ccSide.Quit() 1181 1182 //call's init and does some PUT (after doing some negative testing) 1183 initializeCC(t, chainID, ccname, ccSide, chaincodeSupport) 1184 1185 //chaincode support should not allow dups 1186 handler := &Handler{chaincodeID: ccname + ":0", BuiltinSCCs: chaincodeSupport.BuiltinSCCs} 1187 if err := chaincodeSupport.HandlerRegistry.Register(handler); err == nil { 1188 t.Fatalf("expected re-register to fail") 1189 } 1190 1191 //call's init and does some PUT (after doing some negative testing) 1192 initializeCC(t, chainID2, ccname, ccSide, chaincodeSupport) 1193 1194 //call's invoke and do some GET 1195 invokeCC(t, chainID, ccname, ccSide, chaincodeSupport) 1196 1197 //call's query state range 1198 getQueryStateByRange(t, "", chainID, ccname, ccSide, chaincodeSupport) 1199 1200 //call's cc2cc on the same chaincode only call to chainID2 should succeed 1201 cc2SameCC(t, chainID, chainID2, ccname, ccSide, chaincodeSupport) 1202 1203 //call's cc2cc (variation with syscc calls) 1204 cc2cc(t, chainID, chainID2, ccname, ccSide, chaincodeSupport) 1205 // reset mock 1206 chaincodeSupport.ACLProvider = &mock.ACLProvider{} 1207 1208 //call's query result 1209 getQueryResult(t, "", chainID, ccname, ccSide, chaincodeSupport) 1210 1211 //call's history result 1212 getHistory(t, chainID, ccname, ccSide, chaincodeSupport) 1213 1214 ccSide.Quit() 1215 } 1216 1217 func TestExecuteTimeout(t *testing.T) { 1218 _, cs, cleanup, err := initMockPeer("testchannel") 1219 assert.NoError(t, err) 1220 defer cleanup() 1221 1222 tests := []struct { 1223 executeTimeout time.Duration 1224 installTimeout time.Duration 1225 namespace string 1226 command string 1227 expectedTimeout time.Duration 1228 }{ 1229 { 1230 executeTimeout: time.Second, 1231 installTimeout: time.Minute, 1232 namespace: "lscc", 1233 command: "install", 1234 expectedTimeout: time.Minute, 1235 }, 1236 { 1237 executeTimeout: time.Minute, 1238 installTimeout: time.Second, 1239 namespace: "lscc", 1240 command: "install", 1241 expectedTimeout: time.Minute, 1242 }, 1243 { 1244 executeTimeout: time.Second, 1245 installTimeout: time.Minute, 1246 namespace: "_lifecycle", 1247 command: "InstallChaincode", 1248 expectedTimeout: time.Minute, 1249 }, 1250 { 1251 executeTimeout: time.Minute, 1252 installTimeout: time.Second, 1253 namespace: "_lifecycle", 1254 command: "InstallChaincode", 1255 expectedTimeout: time.Minute, 1256 }, 1257 { 1258 executeTimeout: time.Second, 1259 installTimeout: time.Minute, 1260 namespace: "_lifecycle", 1261 command: "anything", 1262 expectedTimeout: time.Second, 1263 }, 1264 { 1265 executeTimeout: time.Second, 1266 installTimeout: time.Minute, 1267 namespace: "lscc", 1268 command: "anything", 1269 expectedTimeout: time.Second, 1270 }, 1271 { 1272 executeTimeout: time.Second, 1273 installTimeout: time.Minute, 1274 namespace: "anything", 1275 command: "", 1276 expectedTimeout: time.Second, 1277 }, 1278 } 1279 for _, tt := range tests { 1280 t.Run(tt.namespace+"_"+tt.command, func(t *testing.T) { 1281 cs.ExecuteTimeout = tt.executeTimeout 1282 cs.InstallTimeout = tt.installTimeout 1283 input := &pb.ChaincodeInput{Args: util.ToChaincodeArgs(tt.command)} 1284 1285 result := cs.executeTimeout(tt.namespace, input) 1286 assert.Equalf(t, tt.expectedTimeout, result, "want %s, got %s", tt.expectedTimeout, result) 1287 }) 1288 } 1289 } 1290 1291 func TestMaxDuration(t *testing.T) { 1292 tests := []struct { 1293 durations []time.Duration 1294 expected time.Duration 1295 }{ 1296 { 1297 durations: []time.Duration{}, 1298 expected: time.Duration(0), 1299 }, 1300 { 1301 durations: []time.Duration{time.Second, time.Hour, time.Minute}, 1302 expected: time.Hour, 1303 }, 1304 { 1305 durations: []time.Duration{-time.Second}, 1306 expected: time.Duration(0), 1307 }, 1308 } 1309 for _, tt := range tests { 1310 result := maxDuration(tt.durations...) 1311 assert.Equalf(t, tt.expected, result, "want %s got %s", tt.expected, result) 1312 } 1313 } 1314 1315 func startTxSimulation(peerInstance *peer.Peer, channelID string, txid string) (ledger.TxSimulator, ledger.HistoryQueryExecutor, error) { 1316 lgr := peerInstance.GetLedger(channelID) 1317 txsim, err := lgr.NewTxSimulator(txid) 1318 if err != nil { 1319 return nil, nil, err 1320 } 1321 historyQueryExecutor, err := lgr.NewHistoryQueryExecutor() 1322 if err != nil { 1323 return nil, nil, err 1324 } 1325 1326 return txsim, historyQueryExecutor, nil 1327 } 1328 1329 func endTxSimulationCIS(peerInstance *peer.Peer, channelID string, ccid *pb.ChaincodeID, txid string, txsim ledger.TxSimulator, payload []byte, commit bool, cis *pb.ChaincodeInvocationSpec, blockNumber uint64) error { 1330 // get serialized version of the signer 1331 ss, err := signer.Serialize() 1332 if err != nil { 1333 return err 1334 } 1335 1336 // get a proposal - we need it to get a transaction 1337 prop, returnedTxid, err := protoutil.CreateProposalFromCISAndTxid(txid, common.HeaderType_ENDORSER_TRANSACTION, channelID, cis, ss) 1338 if err != nil { 1339 return err 1340 } 1341 if returnedTxid != txid { 1342 return errors.New("txids are not same") 1343 } 1344 1345 return endTxSimulation(peerInstance, channelID, ccid, txsim, payload, commit, prop, blockNumber) 1346 } 1347 1348 //getting a crash from ledger.Commit when doing concurrent invokes 1349 //It is likely intentional that ledger.Commit is serial (ie, the real 1350 //Committer will invoke this serially on each block). Mimic that here 1351 //by forcing serialization of the ledger.Commit call. 1352 // 1353 //NOTE-this should NOT have any effect on the older serial tests. 1354 //This affects only the tests in concurrent_test.go which call these 1355 //concurrently (100 concurrent invokes followed by 100 concurrent queries) 1356 var _commitLock_ sync.Mutex 1357 1358 func endTxSimulation(peerInstance *peer.Peer, channelID string, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error { 1359 txsim.Done() 1360 if lgr := peerInstance.GetLedger(channelID); lgr != nil { 1361 if commit { 1362 var txSimulationResults *ledger.TxSimulationResults 1363 var txSimulationBytes []byte 1364 var err error 1365 1366 txsim.Done() 1367 1368 //get simulation results 1369 if txSimulationResults, err = txsim.GetTxSimulationResults(); err != nil { 1370 return err 1371 } 1372 if txSimulationBytes, err = txSimulationResults.GetPubSimulationBytes(); err != nil { 1373 return err 1374 } 1375 // assemble a (signed) proposal response message 1376 resp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200}, 1377 txSimulationBytes, nil, ccid, signer) 1378 if err != nil { 1379 return err 1380 } 1381 1382 // get the envelope 1383 env, err := protoutil.CreateSignedTx(prop, signer, resp) 1384 if err != nil { 1385 return err 1386 } 1387 1388 envBytes, err := protoutil.GetBytesEnvelope(env) 1389 if err != nil { 1390 return err 1391 } 1392 1393 //create the block with 1 transaction 1394 bcInfo, err := lgr.GetBlockchainInfo() 1395 if err != nil { 1396 return err 1397 } 1398 block := protoutil.NewBlock(blockNumber, bcInfo.CurrentBlockHash) 1399 block.Data.Data = [][]byte{envBytes} 1400 txsFilter := cut.NewTxValidationFlagsSetValue(len(block.Data.Data), pb.TxValidationCode_VALID) 1401 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter 1402 1403 //commit the block 1404 1405 //see comment on _commitLock_ 1406 _commitLock_.Lock() 1407 defer _commitLock_.Unlock() 1408 1409 blockAndPvtData := &ledger.BlockAndPvtData{ 1410 Block: block, 1411 PvtData: make(ledger.TxPvtDataMap), 1412 } 1413 1414 // All tests are performed with just one transaction in a block. 1415 // Hence, we can simiplify the procedure of constructing the 1416 // block with private data. There is not enough need to 1417 // add more than one transaction in a block for testing chaincode 1418 // API. 1419 1420 // ASSUMPTION: Only one transaction in a block. 1421 seqInBlock := uint64(0) 1422 1423 if txSimulationResults.PvtSimulationResults != nil { 1424 blockAndPvtData.PvtData[seqInBlock] = &ledger.TxPvtData{ 1425 SeqInBlock: seqInBlock, 1426 WriteSet: txSimulationResults.PvtSimulationResults, 1427 } 1428 } 1429 1430 if err := lgr.CommitLegacy(blockAndPvtData, &ledger.CommitOptions{}); err != nil { 1431 return err 1432 } 1433 } 1434 } 1435 1436 return nil 1437 } 1438 1439 func TestMain(m *testing.M) { 1440 var err error 1441 1442 msptesttools.LoadMSPSetupForTesting() 1443 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1444 if err != nil { 1445 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err) 1446 os.Exit(-1) 1447 return 1448 } 1449 signer, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 1450 if err != nil { 1451 fmt.Print("Could not initialize msp/signer") 1452 os.Exit(-1) 1453 return 1454 } 1455 1456 setupTestConfig() 1457 flogging.ActivateSpec("chaincode=debug") 1458 os.Exit(m.Run()) 1459 } 1460 1461 func setupTestConfig() { 1462 flag.Parse() 1463 1464 // Now set the configuration file 1465 viper.SetEnvPrefix("CORE") 1466 viper.AutomaticEnv() 1467 replacer := strings.NewReplacer(".", "_") 1468 viper.SetEnvKeyReplacer(replacer) 1469 viper.SetConfigName("chaincodetest") // name of config file (without extension) 1470 viper.AddConfigPath("./") // path to look for the config file in 1471 err := viper.ReadInConfig() // Find and read the config file 1472 if err != nil { // Handle errors reading the config file 1473 panic(fmt.Errorf("Fatal error config file: %s \n", err)) 1474 } 1475 1476 // Init the BCCSP 1477 err = factory.InitFactories(nil) 1478 if err != nil { 1479 panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) 1480 } 1481 } 1482 1483 var signer msp.SigningIdentity 1484 1485 func newPolicyChecker(peerInstance *peer.Peer) policy.PolicyChecker { 1486 return policy.NewPolicyChecker( 1487 policies.PolicyManagerGetterFunc(peerInstance.GetPolicyManager), 1488 &policymocks.MockIdentityDeserializer{ 1489 Identity: []byte("Admin"), 1490 Msg: []byte("msg1"), 1491 }, 1492 &policymocks.MockMSPPrincipalGetter{Principal: []byte("Admin")}, 1493 ) 1494 }