github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/core/chaincode/exectransaction_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 "bytes" 11 "encoding/json" 12 "errors" 13 "flag" 14 "fmt" 15 "io/ioutil" 16 "net" 17 "os" 18 "path/filepath" 19 "reflect" 20 "strconv" 21 "strings" 22 "sync" 23 "testing" 24 "time" 25 26 "github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest" 27 28 docker "github.com/fsouza/go-dockerclient" 29 "github.com/golang/protobuf/proto" 30 "github.com/hyperledger/fabric-chaincode-go/shim" 31 "github.com/hyperledger/fabric-protos-go/common" 32 pb "github.com/hyperledger/fabric-protos-go/peer" 33 "github.com/hyperledger/fabric/bccsp/factory" 34 "github.com/hyperledger/fabric/bccsp/sw" 35 "github.com/hyperledger/fabric/common/channelconfig" 36 "github.com/hyperledger/fabric/common/crypto/tlsgen" 37 "github.com/hyperledger/fabric/common/flogging" 38 "github.com/hyperledger/fabric/common/metrics/disabled" 39 40 "github.com/hyperledger/fabric/common/policies" 41 "github.com/hyperledger/fabric/common/util" 42 "github.com/hyperledger/fabric/core/aclmgmt" 43 "github.com/hyperledger/fabric/core/chaincode/lifecycle" 44 "github.com/hyperledger/fabric/core/chaincode/mock" 45 cm "github.com/hyperledger/fabric/core/chaincode/mock" 46 "github.com/hyperledger/fabric/core/chaincode/persistence" 47 "github.com/hyperledger/fabric/core/chaincode/platforms" 48 "github.com/hyperledger/fabric/core/chaincode/platforms/golang" 49 "github.com/hyperledger/fabric/core/comm" 50 "github.com/hyperledger/fabric/core/common/ccprovider" 51 "github.com/hyperledger/fabric/core/config" 52 "github.com/hyperledger/fabric/core/container" 53 "github.com/hyperledger/fabric/core/container/dockercontroller" 54 "github.com/hyperledger/fabric/core/ledger" 55 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 56 ledgermock "github.com/hyperledger/fabric/core/ledger/mock" 57 cut "github.com/hyperledger/fabric/core/ledger/util" 58 "github.com/hyperledger/fabric/core/peer" 59 "github.com/hyperledger/fabric/core/policy" 60 policymocks "github.com/hyperledger/fabric/core/policy/mocks" 61 "github.com/hyperledger/fabric/core/scc" 62 "github.com/hyperledger/fabric/core/scc/lscc" 63 "github.com/hyperledger/fabric/internal/peer/packaging" 64 "github.com/hyperledger/fabric/msp" 65 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 66 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 67 "github.com/hyperledger/fabric/protoutil" 68 "github.com/spf13/viper" 69 "github.com/stretchr/testify/assert" 70 "github.com/stretchr/testify/require" 71 "google.golang.org/grpc" 72 ) 73 74 //initialize peer and start up. If security==enabled, login as vp 75 func initPeer(channelIDs ...string) (*cm.Lifecycle, net.Listener, *ChaincodeSupport, func(), error) { 76 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 77 if err != nil { 78 return nil, nil, nil, nil, fmt.Errorf("failed to create cryptoProvider %s", err) 79 } 80 81 peerInstance := &peer.Peer{CryptoProvider: cryptoProvider} 82 grpcServer := grpc.NewServer() 83 84 lis, err := net.Listen("tcp", ":0") 85 if err != nil { 86 return nil, nil, nil, nil, fmt.Errorf("failed to start peer listener %s", err) 87 } 88 _, localPort, err := net.SplitHostPort(lis.Addr().String()) 89 if err != nil { 90 return nil, nil, nil, nil, fmt.Errorf("failed to get port: %s", err) 91 } 92 localIP, err := comm.GetLocalIP() 93 if err != nil { 94 return nil, nil, nil, nil, fmt.Errorf("failed to get local IP: %s", err) 95 } 96 97 peerAddress := net.JoinHostPort(localIP, localPort) 98 99 tempdir, err := ioutil.TempDir("", "chaincode") 100 if err != nil { 101 panic(fmt.Sprintf("failed to create temporary directory: %s", err)) 102 } 103 104 lgrInitializer := ledgermgmttest.NewInitializer(filepath.Join(tempdir, "ledgersData")) 105 lgrInitializer.Config.HistoryDBConfig = &ledger.HistoryDBConfig{ 106 Enabled: true, 107 } 108 peerInstance.LedgerMgr = ledgermgmt.NewLedgerMgr(lgrInitializer) 109 ccprovider.SetChaincodesPath(tempdir) 110 ca, _ := tlsgen.NewCA() 111 pr := platforms.NewRegistry(&golang.Platform{}) 112 mockAclProvider := &mock.ACLProvider{} 113 builtinSCCs := map[string]struct{}{"lscc": {}} 114 115 client, err := docker.NewClientFromEnv() 116 if err != nil { 117 return nil, nil, nil, nil, err 118 } 119 120 containerRouter := &container.Router{ 121 DockerBuilder: &dockercontroller.DockerVM{ 122 PeerID: "", 123 NetworkID: "", 124 BuildMetrics: dockercontroller.NewBuildMetrics(&disabled.Provider{}), 125 Client: client, 126 PlatformBuilder: &platforms.Builder{ 127 Registry: pr, 128 Client: client, 129 }, 130 }, 131 PackageProvider: &persistence.FallbackPackageLocator{ 132 ChaincodePackageLocator: &persistence.ChaincodePackageLocator{}, 133 LegacyCCPackageLocator: &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider}, 134 }, 135 } 136 137 buildRegistry := &container.BuildRegistry{} 138 139 lsccImpl := &lscc.SCC{ 140 BuiltinSCCs: map[string]struct{}{"lscc": {}}, 141 Support: &lscc.SupportImpl{ 142 GetMSPIDs: peerInstance.GetMSPIDs, 143 }, 144 SCCProvider: &lscc.PeerShim{Peer: peerInstance}, 145 ACLProvider: mockAclProvider, 146 GetMSPIDs: peerInstance.GetMSPIDs, 147 PolicyChecker: newPolicyChecker(peerInstance), 148 BCCSP: cryptoProvider, 149 BuildRegistry: buildRegistry, 150 ChaincodeBuilder: containerRouter, 151 } 152 153 ml := &cm.Lifecycle{} 154 ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) { 155 switch name { 156 case "lscc": 157 return &lifecycle.ChaincodeEndorsementInfo{ 158 ChaincodeID: "lscc.syscc", 159 }, nil 160 default: 161 return &lifecycle.ChaincodeEndorsementInfo{ 162 ChaincodeID: name + ":0", 163 }, nil 164 } 165 } 166 globalConfig := &Config{ 167 TLSEnabled: false, 168 Keepalive: time.Second, 169 StartupTimeout: 3 * time.Minute, 170 ExecuteTimeout: 30 * time.Second, 171 LogLevel: "info", 172 ShimLogLevel: "warning", 173 LogFormat: "TEST: [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}", 174 TotalQueryLimit: 10000, 175 } 176 containerRuntime := &ContainerRuntime{ 177 BuildRegistry: buildRegistry, 178 ContainerRouter: containerRouter, 179 } 180 userRunsCC := false 181 metricsProviders := &disabled.Provider{} 182 chaincodeHandlerRegistry := NewHandlerRegistry(userRunsCC) 183 chaincodeLauncher := &RuntimeLauncher{ 184 Metrics: NewLaunchMetrics(metricsProviders), 185 Registry: chaincodeHandlerRegistry, 186 Runtime: containerRuntime, 187 StartupTimeout: globalConfig.StartupTimeout, 188 CACert: ca.CertBytes(), 189 PeerAddress: peerAddress, 190 } 191 chaincodeSupport := &ChaincodeSupport{ 192 ACLProvider: aclmgmt.NewACLProvider( 193 func(string) channelconfig.Resources { return nil }, 194 newPolicyChecker(peerInstance), 195 ), 196 AppConfig: peerInstance, 197 DeployedCCInfoProvider: &ledgermock.DeployedChaincodeInfoProvider{}, 198 ExecuteTimeout: globalConfig.ExecuteTimeout, 199 HandlerMetrics: NewHandlerMetrics(metricsProviders), 200 HandlerRegistry: chaincodeHandlerRegistry, 201 Keepalive: globalConfig.Keepalive, 202 Launcher: chaincodeLauncher, 203 Lifecycle: ml, 204 Peer: peerInstance, 205 Runtime: containerRuntime, 206 BuiltinSCCs: builtinSCCs, 207 TotalQueryLimit: globalConfig.TotalQueryLimit, 208 UserRunsCC: userRunsCC, 209 } 210 pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport) 211 212 scc.DeploySysCC(lsccImpl, chaincodeSupport) 213 214 go grpcServer.Serve(lis) 215 216 cleanup := func() { 217 finitPeer(peerInstance, lis, channelIDs...) 218 os.RemoveAll(tempdir) 219 } 220 221 return ml, lis, chaincodeSupport, cleanup, nil 222 } 223 224 func finitPeer(peerInstance *peer.Peer, lis net.Listener, chainIDs ...string) { 225 if lis != nil { 226 closeListenerAndSleep(lis) 227 } 228 for _, c := range chainIDs { 229 if lgr := peerInstance.GetLedger(c); lgr != nil { 230 lgr.Close() 231 } 232 } 233 peerInstance.LedgerMgr.Close() 234 ledgerPath := config.GetPath("peer.fileSystemPath") 235 os.RemoveAll(ledgerPath) 236 os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger")) 237 } 238 239 func startTxSimulation(peerInstance *peer.Peer, channelID string, txid string) (ledger.TxSimulator, ledger.HistoryQueryExecutor, error) { 240 lgr := peerInstance.GetLedger(channelID) 241 txsim, err := lgr.NewTxSimulator(txid) 242 if err != nil { 243 return nil, nil, err 244 } 245 historyQueryExecutor, err := lgr.NewHistoryQueryExecutor() 246 if err != nil { 247 return nil, nil, err 248 } 249 250 return txsim, historyQueryExecutor, nil 251 } 252 253 func endTxSimulationCDS(peerInstance *peer.Peer, channelID string, txsim ledger.TxSimulator, payload []byte, commit bool, cds *pb.ChaincodeDeploymentSpec, blockNumber uint64) error { 254 // get serialized version of the signer 255 ss, err := signer.Serialize() 256 if err != nil { 257 return err 258 } 259 260 // get lscc ChaincodeID 261 lsccid := &pb.ChaincodeID{ 262 Name: "lscc", 263 } 264 265 // get a proposal - we need it to get a transaction 266 prop, _, err := protoutil.CreateDeployProposalFromCDS(channelID, cds, ss, nil, nil, nil, nil) 267 if err != nil { 268 return err 269 } 270 271 return endTxSimulation(peerInstance, channelID, lsccid, txsim, payload, commit, prop, blockNumber) 272 } 273 274 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 { 275 // get serialized version of the signer 276 ss, err := signer.Serialize() 277 if err != nil { 278 return err 279 } 280 281 // get a proposal - we need it to get a transaction 282 prop, returnedTxid, err := protoutil.CreateProposalFromCISAndTxid(txid, common.HeaderType_ENDORSER_TRANSACTION, channelID, cis, ss) 283 if err != nil { 284 return err 285 } 286 if returnedTxid != txid { 287 return errors.New("txids are not same") 288 } 289 290 return endTxSimulation(peerInstance, channelID, ccid, txsim, payload, commit, prop, blockNumber) 291 } 292 293 //getting a crash from ledger.Commit when doing concurrent invokes 294 //It is likely intentional that ledger.Commit is serial (ie, the real 295 //Committer will invoke this serially on each block). Mimic that here 296 //by forcing serialization of the ledger.Commit call. 297 // 298 //NOTE-this should NOT have any effect on the older serial tests. 299 //This affects only the tests in concurrent_test.go which call these 300 //concurrently (100 concurrent invokes followed by 100 concurrent queries) 301 var _commitLock_ sync.Mutex 302 303 func endTxSimulation(peerInstance *peer.Peer, channelID string, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error { 304 txsim.Done() 305 if lgr := peerInstance.GetLedger(channelID); lgr != nil { 306 if commit { 307 var txSimulationResults *ledger.TxSimulationResults 308 var txSimulationBytes []byte 309 var err error 310 311 txsim.Done() 312 313 //get simulation results 314 if txSimulationResults, err = txsim.GetTxSimulationResults(); err != nil { 315 return err 316 } 317 if txSimulationBytes, err = txSimulationResults.GetPubSimulationBytes(); err != nil { 318 return err 319 } 320 // assemble a (signed) proposal response message 321 resp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200}, 322 txSimulationBytes, nil, ccid, signer) 323 if err != nil { 324 return err 325 } 326 327 // get the envelope 328 env, err := protoutil.CreateSignedTx(prop, signer, resp) 329 if err != nil { 330 return err 331 } 332 333 envBytes, err := protoutil.GetBytesEnvelope(env) 334 if err != nil { 335 return err 336 } 337 338 //create the block with 1 transaction 339 bcInfo, err := lgr.GetBlockchainInfo() 340 if err != nil { 341 return err 342 } 343 block := protoutil.NewBlock(blockNumber, bcInfo.CurrentBlockHash) 344 block.Data.Data = [][]byte{envBytes} 345 txsFilter := cut.NewTxValidationFlagsSetValue(len(block.Data.Data), pb.TxValidationCode_VALID) 346 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter 347 348 //commit the block 349 350 //see comment on _commitLock_ 351 _commitLock_.Lock() 352 defer _commitLock_.Unlock() 353 354 blockAndPvtData := &ledger.BlockAndPvtData{ 355 Block: block, 356 PvtData: make(ledger.TxPvtDataMap), 357 } 358 359 // All tests are performed with just one transaction in a block. 360 // Hence, we can simiplify the procedure of constructing the 361 // block with private data. There is not enough need to 362 // add more than one transaction in a block for testing chaincode 363 // API. 364 365 // ASSUMPTION: Only one transaction in a block. 366 seqInBlock := uint64(0) 367 368 if txSimulationResults.PvtSimulationResults != nil { 369 blockAndPvtData.PvtData[seqInBlock] = &ledger.TxPvtData{ 370 SeqInBlock: seqInBlock, 371 WriteSet: txSimulationResults.PvtSimulationResults, 372 } 373 } 374 375 if err := lgr.CommitLegacy(blockAndPvtData, &ledger.CommitOptions{}); err != nil { 376 return err 377 } 378 } 379 } 380 381 return nil 382 } 383 384 // Build a chaincode. 385 func getDeploymentSpec(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) { 386 fmt.Printf("getting deployment spec for chaincode spec: %v\n", spec) 387 codePackageBytes, err := packaging.NewRegistry(&golang.Platform{}).GetDeploymentPayload(spec.Type.String(), spec.ChaincodeId.Path) 388 if err != nil { 389 return nil, err 390 } 391 392 cdDeploymentSpec := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes} 393 return cdDeploymentSpec, nil 394 } 395 396 //getDeployLSCCSpec gets the spec for the chaincode deployment to be sent to LSCC 397 func getDeployLSCCSpec(channelID string, cds *pb.ChaincodeDeploymentSpec, ccp *pb.CollectionConfigPackage) (*pb.ChaincodeInvocationSpec, error) { 398 b, err := proto.Marshal(cds) 399 if err != nil { 400 return nil, err 401 } 402 403 var ccpBytes []byte 404 if ccp != nil { 405 if ccpBytes, err = proto.Marshal(ccp); err != nil { 406 return nil, err 407 } 408 } 409 invokeInput := &pb.ChaincodeInput{Args: [][]byte{ 410 []byte("deploy"), // function name 411 []byte(channelID), // chaincode name to deploy 412 b, // chaincode deployment spec 413 }} 414 415 if ccpBytes != nil { 416 // SignaturePolicyEnvelope, escc, vscc, CollectionConfigPackage 417 invokeInput.Args = append(invokeInput.Args, nil, nil, nil, ccpBytes) 418 } 419 420 //wrap the deployment in an invocation spec to lscc... 421 lsccSpec := &pb.ChaincodeInvocationSpec{ 422 ChaincodeSpec: &pb.ChaincodeSpec{ 423 Type: pb.ChaincodeSpec_GOLANG, 424 ChaincodeId: &pb.ChaincodeID{Name: "lscc"}, 425 Input: invokeInput, 426 }} 427 428 return lsccSpec, nil 429 } 430 431 // Deploy a chaincode - i.e., build and initialize. 432 func deploy(channelID string, ccContext *CCContext, spec *pb.ChaincodeSpec, blockNumber uint64, chaincodeSupport *ChaincodeSupport) (resp *pb.Response, err error) { 433 // First build and get the deployment spec 434 cdDeploymentSpec, err := getDeploymentSpec(spec) 435 if err != nil { 436 return nil, err 437 } 438 return deploy2(channelID, ccContext, cdDeploymentSpec, nil, blockNumber, chaincodeSupport) 439 } 440 441 func deployWithCollectionConfigs(channelID string, ccContext *CCContext, spec *pb.ChaincodeSpec, 442 collectionConfigPkg *pb.CollectionConfigPackage, blockNumber uint64, chaincodeSupport *ChaincodeSupport) (resp *pb.Response, err error) { 443 // First build and get the deployment spec 444 cdDeploymentSpec, err := getDeploymentSpec(spec) 445 if err != nil { 446 return nil, err 447 } 448 return deploy2(channelID, ccContext, cdDeploymentSpec, collectionConfigPkg, blockNumber, chaincodeSupport) 449 } 450 451 func deploy2(channelID string, ccContext *CCContext, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec, 452 collectionConfigPkg *pb.CollectionConfigPackage, blockNumber uint64, chaincodeSupport *ChaincodeSupport) (resp *pb.Response, err error) { 453 cis, err := getDeployLSCCSpec(channelID, chaincodeDeploymentSpec, collectionConfigPkg) 454 if err != nil { 455 return nil, fmt.Errorf("Error creating lscc spec : %s\n", err) 456 } 457 458 uuid := util.GenerateUUID() 459 txsim, hqe, err := startTxSimulation(chaincodeSupport.Peer, channelID, uuid) 460 sprop, prop := protoutil.MockSignedEndorserProposal2OrPanic(channelID, cis.ChaincodeSpec, signer) 461 txParams := &ccprovider.TransactionParams{ 462 TxID: uuid, 463 ChannelID: channelID, 464 TXSimulator: txsim, 465 HistoryQueryExecutor: hqe, 466 SignedProp: sprop, 467 Proposal: prop, 468 } 469 if err != nil { 470 return nil, fmt.Errorf("Failed to get handle to simulator: %s ", err) 471 } 472 473 defer func() { 474 //no error, lets try commit 475 if err == nil { 476 //capture returned error from commit 477 err = endTxSimulationCDS(chaincodeSupport.Peer, channelID, txsim, []byte("deployed"), true, chaincodeDeploymentSpec, blockNumber) 478 } else { 479 //there was an error, just close simulation and return that 480 endTxSimulationCDS(chaincodeSupport.Peer, channelID, txsim, []byte("deployed"), false, chaincodeDeploymentSpec, blockNumber) 481 } 482 }() 483 484 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 485 if err != nil { 486 return nil, fmt.Errorf("Failed to create default cryptoProvider: %s ", err) 487 } 488 ccinfoFSImpl := &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider} 489 //ignore existence errors 490 ccinfoFSImpl.PutChaincode(chaincodeDeploymentSpec) 491 492 //write to lscc 493 if _, _, err = chaincodeSupport.Execute(txParams, "lscc", cis.ChaincodeSpec.Input); err != nil { 494 return nil, fmt.Errorf("Error deploying chaincode (1): %s", err) 495 } 496 497 if resp, _, err = chaincodeSupport.ExecuteLegacyInit(txParams, ccContext.Name, ccContext.Version, chaincodeDeploymentSpec.ChaincodeSpec.Input); err != nil { 498 return nil, fmt.Errorf("Error deploying chaincode(2): %s", err) 499 } 500 501 return resp, nil 502 } 503 504 // Invoke a chaincode. 505 func invoke(channelID string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte, chaincodeSupport *ChaincodeSupport) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) { 506 return invokeWithVersion(channelID, spec.GetChaincodeId().Version, spec, blockNumber, creator, chaincodeSupport) 507 } 508 509 // Invoke a chaincode with version (needed for upgrade) 510 func invokeWithVersion(channelID string, version string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte, chaincodeSupport *ChaincodeSupport) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) { 511 cdInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} 512 513 // Now create the Transactions message and send to Peer. 514 uuid = util.GenerateUUID() 515 516 txsim, hqe, err := startTxSimulation(chaincodeSupport.Peer, channelID, uuid) 517 if err != nil { 518 return nil, uuid, nil, fmt.Errorf("Failed to get handle to simulator: %s ", err) 519 } 520 521 defer func() { 522 //no error, lets try commit 523 if err == nil { 524 //capture returned error from commit 525 err = endTxSimulationCIS(chaincodeSupport.Peer, channelID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), true, cdInvocationSpec, blockNumber) 526 } else { 527 //there was an error, just close simulation and return that 528 endTxSimulationCIS(chaincodeSupport.Peer, channelID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), false, cdInvocationSpec, blockNumber) 529 } 530 }() 531 532 if len(creator) == 0 { 533 creator = []byte("Admin") 534 } 535 sprop, prop := protoutil.MockSignedEndorserProposalOrPanic(channelID, spec, creator, []byte("msg1")) 536 var resp *pb.Response 537 txParams := &ccprovider.TransactionParams{ 538 TxID: uuid, 539 ChannelID: channelID, 540 TXSimulator: txsim, 541 HistoryQueryExecutor: hqe, 542 SignedProp: sprop, 543 Proposal: prop, 544 } 545 546 resp, ccevt, err = chaincodeSupport.Execute(txParams, cdInvocationSpec.ChaincodeSpec.ChaincodeId.Name, cdInvocationSpec.ChaincodeSpec.Input) 547 if err != nil { 548 return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err) 549 } 550 if resp.Status != shim.OK { 551 return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", resp.Message) 552 } 553 554 return ccevt, uuid, resp.Payload, err 555 } 556 557 func closeListenerAndSleep(l net.Listener) { 558 if l != nil { 559 l.Close() 560 time.Sleep(2 * time.Second) 561 } 562 } 563 564 // Check the correctness of the final state after transaction execution. 565 func checkFinalState(peerInstance *peer.Peer, channelID string, ccContext *CCContext, a int, b int) error { 566 txid := util.GenerateUUID() 567 txsim, _, err := startTxSimulation(peerInstance, channelID, txid) 568 if err != nil { 569 return fmt.Errorf("Failed to get handle to simulator: %s ", err) 570 } 571 572 defer txsim.Done() 573 574 cName := ccContext.Name + ":" + ccContext.Version 575 576 // Invoke ledger to get state 577 var Aval, Bval int 578 resbytes, resErr := txsim.GetState(ccContext.Name, "a") 579 if resErr != nil { 580 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 581 } 582 Aval, resErr = strconv.Atoi(string(resbytes)) 583 if resErr != nil { 584 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 585 } 586 if Aval != a { 587 return fmt.Errorf("Incorrect result. Aval %d != %d <%s>", Aval, a, cName) 588 } 589 590 resbytes, resErr = txsim.GetState(ccContext.Name, "b") 591 if resErr != nil { 592 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 593 } 594 Bval, resErr = strconv.Atoi(string(resbytes)) 595 if resErr != nil { 596 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 597 } 598 if Bval != b { 599 return fmt.Errorf("Incorrect result. Bval %d != %d <%s>", Bval, b, cName) 600 } 601 602 // Success 603 fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) 604 return nil 605 } 606 607 const ( 608 chaincodeExample02GolangPath = "github.com/hyperledger/fabric/core/chaincode/testdata/src/chaincodes/example02" 609 chaincodePassthruGolangPath = "github.com/hyperledger/fabric/core/chaincode/testdata/src/chaincodes/passthru" 610 ) 611 612 // Test the execution of a chaincode that invokes another chaincode. 613 func TestChaincodeInvokeChaincode(t *testing.T) { 614 channel1 := "testchannelid" 615 channel2 := channel1 + "2" 616 ml, lis, chaincodeSupport, cleanup, err := initPeer(channel1, channel2) 617 if err != nil { 618 t.Fail() 619 t.Logf("Error creating peer: %s", err) 620 } 621 defer cleanup() 622 defer closeListenerAndSleep(lis) 623 624 mockPolicy := &mock.Policy{} 625 mockPolicy.EvaluateSignedDataReturns(nil) 626 capabilities := &mock.ApplicationCapabilities{} 627 config := &mock.ApplicationConfig{} 628 config.CapabilitiesReturns(capabilities) 629 630 polMgrChannel1 := &mock.PolicyManager{} 631 polMgrChannel1.GetPolicyReturns(mockPolicy, true) 632 resources1 := &mock.Resources{} 633 resources1.PolicyManagerReturns(polMgrChannel1) 634 resources1.ApplicationConfigReturns(config, true) 635 err = peer.CreateMockChannel(chaincodeSupport.Peer, channel1, resources1) 636 if err != nil { 637 t.Fatalf("Failed to create mock channel: %s", err) 638 } 639 640 polMgrChannel2 := &mock.PolicyManager{} 641 polMgrChannel2.GetPolicyReturns(mockPolicy, true) 642 resources2 := &mock.Resources{} 643 resources2.PolicyManagerReturns(polMgrChannel2) 644 resources2.ApplicationConfigReturns(config, true) 645 err = peer.CreateMockChannel(chaincodeSupport.Peer, channel2, resources2) 646 if err != nil { 647 t.Fatalf("Failed to create mock channel: %s", err) 648 } 649 650 peerInstance := chaincodeSupport.Peer 651 652 var nextBlockNumber1 uint64 = 1 653 var nextBlockNumber2 uint64 = 1 654 655 chaincode1Name := "cc_go_" + util.GenerateUUID() 656 chaincode2Name := "cc_go_" + util.GenerateUUID() 657 658 initialA, initialB := 100, 200 659 660 // Deploy first chaincode 661 ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) { 662 switch name { 663 case "lscc": 664 return &lifecycle.ChaincodeEndorsementInfo{ 665 ChaincodeID: "lscc.syscc", 666 }, nil 667 default: 668 return &lifecycle.ChaincodeEndorsementInfo{ 669 ChaincodeID: name + ":0", 670 }, nil 671 } 672 } 673 _, ccContext1, err := deployChaincode( 674 chaincode1Name, 675 "0", 676 pb.ChaincodeSpec_GOLANG, 677 chaincodeExample02GolangPath, 678 util.ToChaincodeArgs("init", "a", strconv.Itoa(initialA), "b", strconv.Itoa(initialB)), 679 channel1, 680 nextBlockNumber1, 681 chaincodeSupport, 682 ) 683 defer stopChaincode(ccContext1, chaincodeSupport) 684 require.NoErrorf(t, err, "error initializing chaincode %s: %s", chaincode1Name, err) 685 nextBlockNumber1++ 686 time.Sleep(time.Second) 687 688 // chaincode2: the chaincode that will call by chaincode1 689 chaincode2Version := "0" 690 chaincode2Type := pb.ChaincodeSpec_GOLANG 691 chaincode2Path := chaincodePassthruGolangPath 692 693 // deploy second chaincode on channel 694 _, ccContext2, err := deployChaincode( 695 chaincode2Name, 696 chaincode2Version, 697 chaincode2Type, 698 chaincode2Path, 699 util.ToChaincodeArgs("init"), 700 channel1, 701 nextBlockNumber1, 702 chaincodeSupport, 703 ) 704 defer stopChaincode(ccContext2, chaincodeSupport) 705 require.NoErrorf(t, err, "Error initializing chaincode %s: %s", chaincode2Name, err) 706 nextBlockNumber1++ 707 time.Sleep(time.Second) 708 709 // Invoke second chaincode passing the first chaincode's name as first param, 710 // which will inturn invoke the first chaincode 711 chaincode2InvokeSpec := &pb.ChaincodeSpec{ 712 Type: chaincode2Type, 713 ChaincodeId: &pb.ChaincodeID{ 714 Name: chaincode2Name, 715 Version: chaincode2Version, 716 }, 717 Input: &pb.ChaincodeInput{ 718 Args: util.ToChaincodeArgs(ccContext1.Name, "invoke", "a", "b", "10", ""), 719 }, 720 } 721 _, _, _, err = invoke(channel1, chaincode2InvokeSpec, nextBlockNumber1, []byte("Alice"), chaincodeSupport) 722 require.NoErrorf(t, err, "error invoking %s: %s", chaincode2Name, err) 723 nextBlockNumber1++ 724 725 // Check the state in the ledger 726 err = checkFinalState(peerInstance, channel1, ccContext1, initialA-10, initialB+10) 727 require.NoErrorf(t, err, "incorrect final state after transaction for %s: %s", chaincode1Name, err) 728 729 // Change the policies of the two channels in such a way: 730 // 1. Alice has reader access to both the channels. 731 // 2. Bob has access only to chainID2. 732 // Therefore the chaincode invocation should fail. 733 734 polMgrChannel1.GetPolicyReturns(&CreatorPolicy{Creators: [][]byte{[]byte("Alice")}}, true) 735 polMgrChannel2.GetPolicyReturns(&CreatorPolicy{Creators: [][]byte{[]byte("Alice"), []byte("Bob")}}, true) 736 737 // deploy chaincode2 on channel2 738 _, ccContext3, err := deployChaincode( 739 chaincode2Name, 740 chaincode2Version, 741 chaincode2Type, 742 chaincode2Path, 743 util.ToChaincodeArgs("init"), 744 channel2, 745 nextBlockNumber2, 746 chaincodeSupport, 747 ) 748 defer stopChaincode(ccContext3, chaincodeSupport) 749 require.NoErrorf(t, err, "error initializing chaincode %s/%s: %s", chaincode2Name, channel2, err) 750 nextBlockNumber2++ 751 time.Sleep(time.Second) 752 753 chaincode2InvokeSpec = &pb.ChaincodeSpec{ 754 Type: chaincode2Type, 755 ChaincodeId: &pb.ChaincodeID{ 756 Name: chaincode2Name, 757 Version: chaincode2Version, 758 }, 759 Input: &pb.ChaincodeInput{ 760 Args: util.ToChaincodeArgs(ccContext1.Name, "invoke", "a", "b", "10", channel1), 761 }, 762 } 763 764 // as Bob, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel 765 _, _, _, err = invoke(channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Bob"), chaincodeSupport) 766 require.Errorf(t, err, "as Bob, invoking <%s/%s> via <%s/%s> should fail, but it succeeded.", ccContext1.Name, channel1, chaincode2Name, channel2) 767 assert.True(t, strings.Contains(err.Error(), "[Creator not recognized [Bob]]")) 768 769 // as Alice, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel 770 _, _, _, err = invoke(channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Alice"), chaincodeSupport) 771 require.NoError(t, err, "as Alice, invoking <%s/%s> via <%s/%s> should should of succeeded, but it failed: %s", ccContext1.Name, channel1, chaincode2Name, channel2, err) 772 nextBlockNumber2++ 773 } 774 775 func stopChaincode(chaincodeCtx *CCContext, chaincodeSupport *ChaincodeSupport) { 776 chaincodeSupport.Runtime.Stop(chaincodeCtx.Name + ":" + chaincodeCtx.Version) 777 } 778 779 // Test the execution of a chaincode that invokes another chaincode with wrong parameters. Should receive error from 780 // from the called chaincode 781 func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { 782 channelID := "testchannelid" 783 784 ml, _, chaincodeSupport, cleanup, err := initPeer(channelID) 785 if err != nil { 786 t.Fail() 787 t.Logf("Error creating peer: %s", err) 788 } 789 defer cleanup() 790 791 polMgr := &mock.PolicyManager{} 792 mockPolicy := &mock.Policy{} 793 mockPolicy.EvaluateIdentitiesReturns(nil) 794 mockPolicy.EvaluateSignedDataReturns(nil) 795 polMgr.GetPolicyReturns(mockPolicy, true) 796 capabilities := &mock.ApplicationCapabilities{} 797 config := &mock.ApplicationConfig{} 798 config.CapabilitiesReturns(capabilities) 799 resources := &mock.Resources{} 800 resources.PolicyManagerReturns(polMgr) 801 resources.ApplicationConfigReturns(config, true) 802 803 peer.CreateMockChannel(chaincodeSupport.Peer, channelID, resources) 804 805 ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) { 806 switch name { 807 case "lscc": 808 return &lifecycle.ChaincodeEndorsementInfo{ 809 ChaincodeID: "lscc.syscc", 810 }, nil 811 default: 812 return &lifecycle.ChaincodeEndorsementInfo{ 813 ChaincodeID: name + ":0", 814 }, nil 815 } 816 } 817 818 // Deploy first chaincode 819 cID1 := &pb.ChaincodeID{Name: "example02", Path: chaincodeExample02GolangPath, Version: "0"} 820 f := "init" 821 args := util.ToChaincodeArgs(f, "a", "100", "b", "200") 822 823 spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} 824 825 ccContext1 := &CCContext{ 826 Name: "example02", 827 Version: "0", 828 } 829 830 var nextBlockNumber uint64 = 1 831 defer chaincodeSupport.Runtime.Stop(cID1.Name + ":" + cID1.Version) 832 833 _, err = deploy(channelID, ccContext1, spec1, nextBlockNumber, chaincodeSupport) 834 nextBlockNumber++ 835 ccID1 := spec1.ChaincodeId.Name 836 if err != nil { 837 t.Fail() 838 t.Logf("Error initializing chaincode %s(%s)", ccID1, err) 839 return 840 } 841 842 time.Sleep(time.Second) 843 844 // Deploy second chaincode 845 cID2 := &pb.ChaincodeID{Name: "pthru", Path: chaincodePassthruGolangPath, Version: "0"} 846 f = "init" 847 args = util.ToChaincodeArgs(f) 848 849 spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 850 851 ccContext2 := &CCContext{ 852 Name: "pthru", 853 Version: "0", 854 } 855 856 defer chaincodeSupport.Runtime.Stop(cID2.Name + ":" + cID2.Version) 857 _, err = deploy(channelID, ccContext2, spec2, nextBlockNumber, chaincodeSupport) 858 nextBlockNumber++ 859 ccID2 := spec2.ChaincodeId.Name 860 if err != nil { 861 t.Fail() 862 t.Logf("Error initializing chaincode %s(%s)", ccID2, err) 863 return 864 } 865 866 time.Sleep(time.Second) 867 868 // Invoke second chaincode, which will inturn invoke the first chaincode but pass bad params 869 f = ccID1 870 args = util.ToChaincodeArgs(f, "invoke", "a", "") 871 872 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 873 // Invoke chaincode 874 _, _, _, err = invoke(channelID, spec2, nextBlockNumber, []byte("Alice"), chaincodeSupport) 875 876 if err == nil { 877 t.Fail() 878 t.Logf("Error invoking <%s>: %s", ccID2, err) 879 return 880 } 881 882 if !strings.Contains(err.Error(), "Incorrect number of arguments. Expecting 3") { 883 t.Fail() 884 t.Logf("Unexpected error %s", err) 885 return 886 } 887 } 888 889 func TestChaincodeInit(t *testing.T) { 890 channelID := "testchannelid" 891 892 _, _, chaincodeSupport, cleanup, err := initPeer(channelID) 893 if err != nil { 894 t.Fail() 895 t.Logf("Error creating peer: %s", err) 896 } 897 898 defer cleanup() 899 900 config := &mock.ApplicationConfig{} 901 config.CapabilitiesReturns(&mock.ApplicationCapabilities{}) 902 resources := &mock.Resources{} 903 resources.ApplicationConfigReturns(config, true) 904 peer.CreateMockChannel(chaincodeSupport.Peer, channelID, resources) 905 906 url := "github.com/hyperledger/fabric/core/chaincode/testdata/src/chaincodes/init_private_data" 907 cID := &pb.ChaincodeID{Name: "init_pvtdata", Path: url, Version: "0"} 908 909 f := "init" 910 args := util.ToChaincodeArgs(f) 911 912 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 913 914 ccContext := &CCContext{ 915 Name: "init_pvtdata", 916 Version: "0", 917 } 918 919 defer chaincodeSupport.Runtime.Stop(cID.Name + ":" + cID.Version) 920 921 var nextBlockNumber uint64 = 1 922 _, err = deploy(channelID, ccContext, spec, nextBlockNumber, chaincodeSupport) 923 assert.Contains(t, err.Error(), "private data APIs are not allowed in chaincode Init") 924 925 url = "github.com/hyperledger/fabric/core/chaincode/testdata/src/chaincodes/init_public_data" 926 cID = &pb.ChaincodeID{Name: "init_public_data", Path: url, Version: "0"} 927 928 f = "init" 929 args = util.ToChaincodeArgs(f) 930 931 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 932 933 ccContext = &CCContext{ 934 Name: "init_public_data", 935 Version: "0", 936 } 937 938 defer chaincodeSupport.Runtime.Stop(cID.Name + ":" + cID.Version) 939 940 resp, err := deploy(channelID, ccContext, spec, nextBlockNumber, chaincodeSupport) 941 assert.NoError(t, err) 942 // why response status is defined as int32 when the status codes are 943 // defined as int (i.e., constant) 944 assert.Equal(t, int32(shim.OK), resp.Status) 945 } 946 947 // Test the invocation of a transaction. 948 func TestQueries(t *testing.T) { 949 // Allow queries test alone so that end to end test can be performed. It takes less than 5 seconds. 950 //testForSkip(t) 951 952 channelID := "testchannelid" 953 954 _, _, chaincodeSupport, cleanup, err := initPeer(channelID) 955 if err != nil { 956 t.Fail() 957 t.Logf("Error creating peer: %s", err) 958 } 959 960 defer cleanup() 961 962 config := &mock.ApplicationConfig{} 963 config.CapabilitiesReturns(&mock.ApplicationCapabilities{}) 964 resources := &mock.Resources{} 965 resources.ApplicationConfigReturns(config, true) 966 peer.CreateMockChannel(chaincodeSupport.Peer, channelID, resources) 967 968 url := "github.com/hyperledger/fabric/core/chaincode/testdata/src/chaincodes/map" 969 cID := &pb.ChaincodeID{Name: "tmap", Path: url, Version: "0"} 970 971 f := "init" 972 args := util.ToChaincodeArgs(f) 973 974 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 975 976 ccContext := &CCContext{ 977 Name: "tmap", 978 Version: "0", 979 } 980 981 defer chaincodeSupport.Runtime.Stop(cID.Name + ":" + cID.Version) 982 983 var nextBlockNumber uint64 = 1 984 _, err = deploy(channelID, ccContext, spec, nextBlockNumber, chaincodeSupport) 985 nextBlockNumber++ 986 ccID := spec.ChaincodeId.Name 987 if err != nil { 988 t.Fail() 989 t.Logf("Error initializing chaincode %s(%s)", ccID, err) 990 return 991 } 992 993 var keys []interface{} 994 // Add 101 marbles for testing range queries and rich queries (for capable ledgers) 995 // The tests will test both range and rich queries and queries with query limits 996 for i := 1; i <= 101; i++ { 997 f = "put" 998 999 // 51 owned by tom, 50 by jerry 1000 owner := "tom" 1001 if i%2 == 0 { 1002 owner = "jerry" 1003 } 1004 1005 // one marble color is red, 100 are blue 1006 color := "blue" 1007 if i == 12 { 1008 color = "red" 1009 } 1010 1011 key := fmt.Sprintf("marble%03d", i) 1012 argsString := fmt.Sprintf("{\"docType\":\"marble\",\"name\":\"%s\",\"color\":\"%s\",\"size\":35,\"owner\":\"%s\"}", key, color, owner) 1013 args = util.ToChaincodeArgs(f, key, argsString) 1014 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1015 _, _, _, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1016 nextBlockNumber++ 1017 1018 if err != nil { 1019 t.Fail() 1020 t.Logf("Error invoking <%s>: %s", ccID, err) 1021 return 1022 } 1023 1024 } 1025 1026 //The following range query for "marble001" to "marble011" should return 10 marbles 1027 f = "keys" 1028 args = util.ToChaincodeArgs(f, "marble001", "marble011") 1029 1030 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1031 _, _, retval, err := invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1032 nextBlockNumber++ 1033 if err != nil { 1034 t.Fail() 1035 t.Logf("Error invoking <%s>: %s", ccID, err) 1036 return 1037 } 1038 1039 err = json.Unmarshal(retval, &keys) 1040 assert.NoError(t, err) 1041 if len(keys) != 10 { 1042 t.Fail() 1043 t.Logf("Error detected with the range query, should have returned 10 but returned %v", len(keys)) 1044 return 1045 } 1046 1047 //FAB-1163- The following range query should timeout and produce an error 1048 //the peer should handle this gracefully and not die 1049 1050 //save the original timeout and set a new timeout of 1 sec 1051 origTimeout := chaincodeSupport.ExecuteTimeout 1052 chaincodeSupport.ExecuteTimeout = time.Duration(1) * time.Second 1053 1054 //chaincode to sleep for 2 secs with timeout 1 1055 args = util.ToChaincodeArgs(f, "marble001", "marble002", "2000") 1056 1057 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1058 _, _, _, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1059 if err == nil { 1060 t.Fail() 1061 t.Logf("expected timeout error but succeeded") 1062 return 1063 } 1064 1065 //restore timeout 1066 chaincodeSupport.ExecuteTimeout = origTimeout 1067 1068 // querying for all marbles will return 101 marbles 1069 // this query should return exactly 101 results (one call to Next()) 1070 //The following range query for "marble001" to "marble102" should return 101 marbles 1071 f = "keys" 1072 args = util.ToChaincodeArgs(f, "marble001", "marble102") 1073 1074 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1075 _, _, retval, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1076 nextBlockNumber++ 1077 if err != nil { 1078 t.Fail() 1079 t.Logf("Error invoking <%s>: %s", ccID, err) 1080 return 1081 } 1082 1083 //unmarshal the results 1084 err = json.Unmarshal(retval, &keys) 1085 assert.NoError(t, err) 1086 1087 //check to see if there are 101 values 1088 //default query limit of 10000 is used, this query is effectively unlimited 1089 if len(keys) != 101 { 1090 t.Fail() 1091 t.Logf("Error detected with the range query, should have returned 101 but returned %v", len(keys)) 1092 return 1093 } 1094 1095 // querying for all simple key. This query should return exactly 101 simple keys (one 1096 // call to Next()) no composite keys. 1097 //The following open ended range query for "" to "" should return 101 marbles 1098 f = "keys" 1099 args = util.ToChaincodeArgs(f, "", "") 1100 1101 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1102 _, _, retval, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1103 nextBlockNumber++ 1104 if err != nil { 1105 t.Fail() 1106 t.Logf("Error invoking <%s>: %s", ccID, err) 1107 return 1108 } 1109 1110 //unmarshal the results 1111 err = json.Unmarshal(retval, &keys) 1112 assert.NoError(t, err) 1113 1114 //check to see if there are 101 values 1115 //default query limit of 10000 is used, this query is effectively unlimited 1116 if len(keys) != 101 { 1117 t.Fail() 1118 t.Logf("Error detected with the range query, should have returned 101 but returned %v", len(keys)) 1119 return 1120 } 1121 1122 type PageResponse struct { 1123 Bookmark string `json:"bookmark"` 1124 Keys []string `json:"keys"` 1125 } 1126 1127 //The following range query for "marble001" to "marble011" should return 10 marbles, in pages of 2 1128 f = "keysByPage" 1129 args = util.ToChaincodeArgs(f, "marble001", "marble011", "2", "") 1130 1131 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1132 _, _, retval, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1133 nextBlockNumber++ 1134 if err != nil { 1135 t.Fail() 1136 t.Logf("Error invoking <%s>: %s", ccID, err) 1137 return 1138 } 1139 queryPage := &PageResponse{} 1140 1141 json.Unmarshal(retval, &queryPage) 1142 1143 expectedResult := []string{"marble001", "marble002"} 1144 1145 if !reflect.DeepEqual(expectedResult, queryPage.Keys) { 1146 t.Fail() 1147 t.Logf("Error detected with the paginated range query. Returned: %v should have returned: %v", queryPage.Keys, expectedResult) 1148 return 1149 } 1150 1151 // query for the next page 1152 args = util.ToChaincodeArgs(f, "marble001", "marble011", "2", queryPage.Bookmark) 1153 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1154 _, _, retval, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1155 nextBlockNumber++ 1156 if err != nil { 1157 t.Fail() 1158 t.Logf("Error invoking <%s>: %s", ccID, err) 1159 return 1160 } 1161 1162 json.Unmarshal(retval, &queryPage) 1163 1164 expectedResult = []string{"marble003", "marble004"} 1165 1166 if !reflect.DeepEqual(expectedResult, queryPage.Keys) { 1167 t.Fail() 1168 t.Logf("Error detected with the paginated range query second page. Returned: %v should have returned: %v %v", queryPage.Keys, expectedResult, queryPage.Bookmark) 1169 return 1170 } 1171 1172 // modifications for history query 1173 f = "put" 1174 args = util.ToChaincodeArgs(f, "marble012", "{\"docType\":\"marble\",\"name\":\"marble012\",\"color\":\"red\",\"size\":30,\"owner\":\"jerry\"}") 1175 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1176 _, _, _, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1177 nextBlockNumber++ 1178 if err != nil { 1179 t.Fail() 1180 t.Logf("Error invoking <%s>: %s", ccID, err) 1181 return 1182 } 1183 1184 f = "put" 1185 args = util.ToChaincodeArgs(f, "marble012", "{\"docType\":\"marble\",\"name\":\"marble012\",\"color\":\"red\",\"size\":30,\"owner\":\"jerry\"}") 1186 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1187 _, _, _, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1188 nextBlockNumber++ 1189 if err != nil { 1190 t.Fail() 1191 t.Logf("Error invoking <%s>: %s", ccID, err) 1192 return 1193 } 1194 1195 //The following history query for "marble12" should return 3 records 1196 f = "history" 1197 args = util.ToChaincodeArgs(f, "marble012") 1198 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1199 _, _, retval, err = invoke(channelID, spec, nextBlockNumber, nil, chaincodeSupport) 1200 nextBlockNumber++ 1201 if err != nil { 1202 t.Fail() 1203 t.Logf("Error invoking <%s>: %s", ccID, err) 1204 return 1205 } 1206 1207 var history []interface{} 1208 err = json.Unmarshal(retval, &history) 1209 assert.NoError(t, err) 1210 if len(history) != 3 { 1211 t.Fail() 1212 t.Logf("Error detected with the history query, should have returned 3 but returned %v", len(history)) 1213 return 1214 } 1215 } 1216 1217 func TestMain(m *testing.M) { 1218 var err error 1219 1220 msptesttools.LoadMSPSetupForTesting() 1221 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1222 if err != nil { 1223 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err) 1224 os.Exit(-1) 1225 return 1226 } 1227 signer, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 1228 if err != nil { 1229 fmt.Print("Could not initialize msp/signer") 1230 os.Exit(-1) 1231 return 1232 } 1233 1234 setupTestConfig() 1235 flogging.ActivateSpec("chaincode=debug") 1236 os.Exit(m.Run()) 1237 } 1238 1239 func setupTestConfig() { 1240 flag.Parse() 1241 1242 // Now set the configuration file 1243 viper.SetEnvPrefix("CORE") 1244 viper.AutomaticEnv() 1245 replacer := strings.NewReplacer(".", "_") 1246 viper.SetEnvKeyReplacer(replacer) 1247 viper.SetConfigName("chaincodetest") // name of config file (without extension) 1248 viper.AddConfigPath("./") // path to look for the config file in 1249 err := viper.ReadInConfig() // Find and read the config file 1250 if err != nil { // Handle errors reading the config file 1251 panic(fmt.Errorf("Fatal error config file: %s \n", err)) 1252 } 1253 1254 // Init the BCCSP 1255 err = factory.InitFactories(nil) 1256 if err != nil { 1257 panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) 1258 } 1259 } 1260 1261 func deployChaincode(name string, version string, chaincodeType pb.ChaincodeSpec_Type, path string, args [][]byte, channel string, nextBlockNumber uint64, chaincodeSupport *ChaincodeSupport) (*pb.Response, *CCContext, error) { 1262 chaincodeSpec := &pb.ChaincodeSpec{ 1263 ChaincodeId: &pb.ChaincodeID{ 1264 Name: name, 1265 Version: version, 1266 Path: path, 1267 }, 1268 Type: chaincodeType, 1269 Input: &pb.ChaincodeInput{ 1270 Args: args, 1271 }, 1272 } 1273 1274 chaincodeCtx := &CCContext{ 1275 Name: name, 1276 Version: version, 1277 } 1278 1279 result, err := deploy(channel, chaincodeCtx, chaincodeSpec, nextBlockNumber, chaincodeSupport) 1280 if err != nil { 1281 return nil, chaincodeCtx, fmt.Errorf("Error deploying <%s:%s>: %s", name, version, err) 1282 } 1283 return result, chaincodeCtx, nil 1284 } 1285 1286 var signer msp.SigningIdentity 1287 1288 type CreatorPolicy struct { 1289 Creators [][]byte 1290 } 1291 1292 // EvaluateSignedData takes a set of SignedData and evaluates whether this set of signatures satisfies the policy 1293 func (c *CreatorPolicy) EvaluateSignedData(signatureSet []*protoutil.SignedData) error { 1294 for _, value := range c.Creators { 1295 if bytes.Equal(signatureSet[0].Identity, value) { 1296 return nil 1297 } 1298 } 1299 return fmt.Errorf("Creator not recognized [%s]", string(signatureSet[0].Identity)) 1300 } 1301 1302 // EvaluateIdentities takes an array of identities and evaluates whether 1303 // they satisfy the policy 1304 func (c *CreatorPolicy) EvaluateIdentities(identities []msp.Identity) error { 1305 return nil 1306 } 1307 1308 func newPolicyChecker(peerInstance *peer.Peer) policy.PolicyChecker { 1309 return policy.NewPolicyChecker( 1310 policies.PolicyManagerGetterFunc(peerInstance.GetPolicyManager), 1311 &policymocks.MockIdentityDeserializer{ 1312 Identity: []byte("Admin"), 1313 Msg: []byte("msg1"), 1314 }, 1315 &policymocks.MockMSPPrincipalGetter{Principal: []byte("Admin")}, 1316 ) 1317 }