github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/chaincode/exectransaction_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package chaincode 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "flag" 23 "fmt" 24 "math/rand" 25 "net" 26 "os" 27 "path/filepath" 28 "runtime" 29 "strconv" 30 "strings" 31 "sync" 32 "testing" 33 "time" 34 35 "github.com/golang/protobuf/proto" 36 "github.com/hyperledger/fabric/bccsp/factory" 37 mockpolicies "github.com/hyperledger/fabric/common/mocks/policies" 38 "github.com/hyperledger/fabric/common/policies" 39 "github.com/hyperledger/fabric/common/util" 40 "github.com/hyperledger/fabric/core/common/ccprovider" 41 "github.com/hyperledger/fabric/core/config" 42 "github.com/hyperledger/fabric/core/container" 43 "github.com/hyperledger/fabric/core/container/ccintf" 44 "github.com/hyperledger/fabric/core/ledger" 45 "github.com/hyperledger/fabric/core/ledger/ledgerconfig" 46 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 47 "github.com/hyperledger/fabric/core/ledger/util/couchdb" 48 "github.com/hyperledger/fabric/core/peer" 49 "github.com/hyperledger/fabric/core/policy" 50 "github.com/hyperledger/fabric/core/policy/mocks" 51 "github.com/hyperledger/fabric/core/scc" 52 "github.com/hyperledger/fabric/core/testutil" 53 "github.com/hyperledger/fabric/msp" 54 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 55 "github.com/hyperledger/fabric/msp/mgmt/testtools" 56 "github.com/hyperledger/fabric/protos/common" 57 pb "github.com/hyperledger/fabric/protos/peer" 58 putils "github.com/hyperledger/fabric/protos/utils" 59 "github.com/spf13/viper" 60 "golang.org/x/net/context" 61 "google.golang.org/grpc" 62 "google.golang.org/grpc/credentials" 63 ) 64 65 var runTests bool 66 67 func testForSkip(t *testing.T) { 68 //run tests 69 if !runTests { 70 t.SkipNow() 71 } 72 } 73 74 //initialize peer and start up. If security==enabled, login as vp 75 func initPeer(chainIDs ...string) (net.Listener, error) { 76 //start clean 77 finitPeer(nil, chainIDs...) 78 79 peer.MockInitialize() 80 81 mspGetter := func(cid string) []string { 82 return []string{"DEFAULT"} 83 } 84 85 peer.MockSetMSPIDGetter(mspGetter) 86 87 var opts []grpc.ServerOption 88 if viper.GetBool("peer.tls.enabled") { 89 creds, err := credentials.NewServerTLSFromFile(config.GetPath("peer.tls.cert.file"), config.GetPath("peer.tls.key.file")) 90 if err != nil { 91 return nil, fmt.Errorf("Failed to generate credentials %v", err) 92 } 93 opts = []grpc.ServerOption{grpc.Creds(creds)} 94 } 95 grpcServer := grpc.NewServer(opts...) 96 97 peerAddress, err := peer.GetLocalAddress() 98 if err != nil { 99 return nil, fmt.Errorf("Error obtaining peer address: %s", err) 100 } 101 lis, err := net.Listen("tcp", peerAddress) 102 if err != nil { 103 return nil, fmt.Errorf("Error starting peer listener %s", err) 104 } 105 106 getPeerEndpoint := func() (*pb.PeerEndpoint, error) { 107 return &pb.PeerEndpoint{Id: &pb.PeerID{Name: "testpeer"}, Address: peerAddress}, nil 108 } 109 110 ccStartupTimeout := time.Duration(chaincodeStartupTimeoutDefault) * time.Millisecond 111 pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout)) 112 113 // Mock policy checker 114 policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{}) 115 116 scc.RegisterSysCCs() 117 118 for _, id := range chainIDs { 119 scc.DeDeploySysCCs(id) 120 if err = peer.MockCreateChain(id); err != nil { 121 closeListenerAndSleep(lis) 122 return nil, err 123 } 124 scc.DeploySysCCs(id) 125 // any chain other than the default testchainid does not have a MSP set up -> create one 126 if id != util.GetTestChainID() { 127 mspmgmt.XXXSetMSPManager(id, mspmgmt.GetManagerForChain(util.GetTestChainID())) 128 } 129 } 130 131 go grpcServer.Serve(lis) 132 133 return lis, nil 134 } 135 136 func finitPeer(lis net.Listener, chainIDs ...string) { 137 if lis != nil { 138 for _, c := range chainIDs { 139 scc.DeDeploySysCCs(c) 140 if lgr := peer.GetLedger(c); lgr != nil { 141 lgr.Close() 142 } 143 } 144 closeListenerAndSleep(lis) 145 } 146 ledgermgmt.CleanupTestEnv() 147 ledgerPath := config.GetPath("peer.fileSystemPath") 148 os.RemoveAll(ledgerPath) 149 os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger")) 150 151 //if couchdb is enabled, then cleanup the test couchdb 152 if ledgerconfig.IsCouchDBEnabled() == true { 153 154 chainID := util.GetTestChainID() 155 156 connectURL := viper.GetString("ledger.state.couchDBConfig.couchDBAddress") 157 username := viper.GetString("ledger.state.couchDBConfig.username") 158 password := viper.GetString("ledger.state.couchDBConfig.password") 159 maxRetries := viper.GetInt("ledger.state.couchDBConfig.maxRetries") 160 maxRetriesOnStartup := viper.GetInt("ledger.state.couchDBConfig.maxRetriesOnStartup") 161 requestTimeout := viper.GetDuration("ledger.state.couchDBConfig.requestTimeout") 162 163 couchInstance, _ := couchdb.CreateCouchInstance(connectURL, username, password, maxRetries, maxRetriesOnStartup, requestTimeout) 164 db := couchdb.CouchDatabase{CouchInstance: *couchInstance, DBName: chainID} 165 //drop the test database 166 db.DropDatabase() 167 168 } 169 } 170 171 func startTxSimulation(ctxt context.Context, chainID string) (context.Context, ledger.TxSimulator, error) { 172 lgr := peer.GetLedger(chainID) 173 txsim, err := lgr.NewTxSimulator() 174 if err != nil { 175 return nil, nil, err 176 } 177 historyQueryExecutor, err := lgr.NewHistoryQueryExecutor() 178 if err != nil { 179 return nil, nil, err 180 } 181 182 ctxt = context.WithValue(ctxt, TXSimulatorKey, txsim) 183 ctxt = context.WithValue(ctxt, HistoryQueryExecutorKey, historyQueryExecutor) 184 return ctxt, txsim, nil 185 } 186 187 func endTxSimulationCDS(chainID string, _ string, txsim ledger.TxSimulator, payload []byte, commit bool, cds *pb.ChaincodeDeploymentSpec, blockNumber uint64) error { 188 // get serialized version of the signer 189 ss, err := signer.Serialize() 190 if err != nil { 191 return err 192 } 193 194 // get lscc ChaincodeID 195 lsccid := &pb.ChaincodeID{ 196 Name: "lscc", 197 Version: util.GetSysCCVersion(), 198 } 199 200 // get a proposal - we need it to get a transaction 201 prop, _, err := putils.CreateDeployProposalFromCDS(chainID, cds, ss, nil, nil, nil) 202 if err != nil { 203 return err 204 } 205 206 return endTxSimulation(chainID, lsccid, txsim, payload, commit, prop, blockNumber) 207 } 208 209 func endTxSimulationCIS(chainID string, ccid *pb.ChaincodeID, _ string, txsim ledger.TxSimulator, payload []byte, commit bool, cis *pb.ChaincodeInvocationSpec, blockNumber uint64) error { 210 // get serialized version of the signer 211 ss, err := signer.Serialize() 212 if err != nil { 213 return err 214 } 215 216 // get a proposal - we need it to get a transaction 217 prop, _, err := putils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, cis, ss) 218 if err != nil { 219 return err 220 } 221 222 return endTxSimulation(chainID, ccid, txsim, payload, commit, prop, blockNumber) 223 } 224 225 //getting a crash from ledger.Commit when doing concurrent invokes 226 //It is likely intentional that ledger.Commit is serial (ie, the real 227 //Committer will invoke this serially on each block). Mimic that here 228 //by forcing serialization of the ledger.Commit call. 229 // 230 //NOTE-this should NOT have any effect on the older serial tests. 231 //This affects only the tests in concurrent_test.go which call these 232 //concurrently (100 concurrent invokes followed by 100 concurrent queries) 233 var _commitLock_ sync.Mutex 234 235 func endTxSimulation(chainID string, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error { 236 txsim.Done() 237 if lgr := peer.GetLedger(chainID); lgr != nil { 238 if commit { 239 var txSimulationResults []byte 240 var err error 241 242 //get simulation results 243 if txSimulationResults, err = txsim.GetTxSimulationResults(); err != nil { 244 return err 245 } 246 247 // assemble a (signed) proposal response message 248 resp, err := putils.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200}, txSimulationResults, nil, ccid, nil, signer) 249 if err != nil { 250 return err 251 } 252 253 // get the envelope 254 env, err := putils.CreateSignedTx(prop, signer, resp) 255 if err != nil { 256 return err 257 } 258 259 envBytes, err := putils.GetBytesEnvelope(env) 260 if err != nil { 261 return err 262 } 263 264 //create the block with 1 transaction 265 block := common.NewBlock(blockNumber, []byte{}) 266 block.Data.Data = [][]byte{envBytes} 267 //commit the block 268 269 //see comment on _commitLock_ 270 _commitLock_.Lock() 271 defer _commitLock_.Unlock() 272 if err := lgr.Commit(block); err != nil { 273 return err 274 } 275 } 276 } 277 278 return nil 279 } 280 281 // Build a chaincode. 282 func getDeploymentSpec(_ context.Context, spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) { 283 fmt.Printf("getting deployment spec for chaincode spec: %v\n", spec) 284 codePackageBytes, err := container.GetChaincodePackageBytes(spec) 285 if err != nil { 286 return nil, err 287 } 288 cdDeploymentSpec := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes} 289 return cdDeploymentSpec, nil 290 } 291 292 //getDeployLSCCSpec gets the spec for the chaincode deployment to be sent to LSCC 293 func getDeployLSCCSpec(chainID string, cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeInvocationSpec, error) { 294 b, err := proto.Marshal(cds) 295 if err != nil { 296 return nil, err 297 } 298 299 sysCCVers := util.GetSysCCVersion() 300 301 //wrap the deployment in an invocation spec to lscc... 302 lsccSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: "lscc", Version: sysCCVers}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("deploy"), []byte(chainID), b}}}} 303 304 return lsccSpec, nil 305 } 306 307 // Deploy a chaincode - i.e., build and initialize. 308 func deploy(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeSpec, blockNumber uint64) (b []byte, err error) { 309 // First build and get the deployment spec 310 cdDeploymentSpec, err := getDeploymentSpec(ctx, spec) 311 if err != nil { 312 return nil, err 313 } 314 315 return deploy2(ctx, cccid, cdDeploymentSpec, blockNumber) 316 } 317 318 func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec, blockNumber uint64) (b []byte, err error) { 319 cis, err := getDeployLSCCSpec(cccid.ChainID, chaincodeDeploymentSpec) 320 if err != nil { 321 return nil, fmt.Errorf("Error creating lscc spec : %s\n", err) 322 } 323 324 ctx, txsim, err := startTxSimulation(ctx, cccid.ChainID) 325 if err != nil { 326 return nil, fmt.Errorf("Failed to get handle to simulator: %s ", err) 327 } 328 329 uuid := util.GenerateUUID() 330 331 cccid.TxID = uuid 332 333 defer func() { 334 //no error, lets try commit 335 if err == nil { 336 //capture returned error from commit 337 err = endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), true, chaincodeDeploymentSpec, blockNumber) 338 } else { 339 //there was an error, just close simulation and return that 340 endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), false, chaincodeDeploymentSpec, blockNumber) 341 } 342 }() 343 344 //ignore existence errors 345 ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec) 346 347 sysCCVers := util.GetSysCCVersion() 348 sprop, prop := putils.MockSignedEndorserProposal2OrPanic(cccid.ChainID, cis.ChaincodeSpec, signer) 349 lsccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, sprop, prop) 350 351 //write to lscc 352 if _, _, err = ExecuteWithErrorFilter(ctx, lsccid, cis); err != nil { 353 return nil, fmt.Errorf("Error deploying chaincode (1): %s", err) 354 } 355 if b, _, err = ExecuteWithErrorFilter(ctx, cccid, chaincodeDeploymentSpec); err != nil { 356 return nil, fmt.Errorf("Error deploying chaincode(2): %s", err) 357 } 358 359 return b, nil 360 } 361 362 // Invoke a chaincode. 363 func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) { 364 return invokeWithVersion(ctx, chainID, spec.GetChaincodeId().Version, spec, blockNumber, creator) 365 } 366 367 // Invoke a chaincode with version (needed for upgrade) 368 func invokeWithVersion(ctx context.Context, chainID string, version string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) { 369 cdInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} 370 371 // Now create the Transactions message and send to Peer. 372 uuid = util.GenerateUUID() 373 374 var txsim ledger.TxSimulator 375 ctx, txsim, err = startTxSimulation(ctx, chainID) 376 if err != nil { 377 return nil, uuid, nil, fmt.Errorf("Failed to get handle to simulator: %s ", err) 378 } 379 380 defer func() { 381 //no error, lets try commit 382 if err == nil { 383 //capture returned error from commit 384 err = endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), true, cdInvocationSpec, blockNumber) 385 } else { 386 //there was an error, just close simulation and return that 387 endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), false, cdInvocationSpec, blockNumber) 388 } 389 }() 390 391 if len(creator) == 0 { 392 creator = []byte("Admin") 393 } 394 sprop, prop := putils.MockSignedEndorserProposalOrPanic(chainID, spec, creator, []byte("msg1")) 395 cccid := ccprovider.NewCCContext(chainID, cdInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, sprop, prop) 396 retval, ccevt, err = ExecuteWithErrorFilter(ctx, cccid, cdInvocationSpec) 397 if err != nil { 398 return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err) 399 } 400 401 return ccevt, uuid, retval, err 402 } 403 404 func closeListenerAndSleep(l net.Listener) { 405 if l != nil { 406 l.Close() 407 time.Sleep(2 * time.Second) 408 } 409 } 410 411 func executeDeployTransaction(t *testing.T, chainID string, name string, url string) { 412 lis, err := initPeer(chainID) 413 if err != nil { 414 t.Fail() 415 t.Logf("Error creating peer: %s", err) 416 } 417 418 defer finitPeer(lis, chainID) 419 420 var ctxt = context.Background() 421 422 f := "init" 423 args := util.ToChaincodeArgs(f, "a", "100", "b", "200") 424 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: url, Version: "0"}, Input: &pb.ChaincodeInput{Args: args}} 425 426 cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil, nil) 427 428 _, err = deploy(ctxt, cccid, spec, 0) 429 430 cID := spec.ChaincodeId.Name 431 if err != nil { 432 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 433 t.Fail() 434 t.Logf("Error deploying <%s>: %s", cID, err) 435 return 436 } 437 438 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 439 } 440 441 // chaincodeQueryChaincode function 442 func _(chainID string, _ string) error { 443 var ctxt = context.Background() 444 445 // Deploy first chaincode 446 url1 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 447 448 cID1 := &pb.ChaincodeID{Name: "example02", Path: url1, Version: "0"} 449 f := "init" 450 args := util.ToChaincodeArgs(f, "a", "100", "b", "200") 451 452 spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} 453 454 cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) 455 456 var nextBlockNumber uint64 457 458 _, err := deploy(ctxt, cccid1, spec1, nextBlockNumber) 459 nextBlockNumber++ 460 461 ccID1 := spec1.ChaincodeId.Name 462 if err != nil { 463 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 464 return fmt.Errorf("Error initializing chaincode %s(%s)", ccID1, err) 465 } 466 467 time.Sleep(time.Second) 468 469 // Deploy second chaincode 470 url2 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example05" 471 472 cID2 := &pb.ChaincodeID{Name: "example05", Path: url2, Version: "0"} 473 f = "init" 474 args = util.ToChaincodeArgs(f, "sum", "0") 475 476 spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 477 478 cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, nil, nil) 479 480 _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) 481 nextBlockNumber++ 482 ccID2 := spec2.ChaincodeId.Name 483 if err != nil { 484 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 485 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 486 return fmt.Errorf("Error initializing chaincode %s(%s)", ccID2, err) 487 } 488 489 time.Sleep(time.Second) 490 491 // Invoke second chaincode, which will inturn query the first chaincode 492 f = "invoke" 493 args = util.ToChaincodeArgs(f, ccID1, "sum") 494 495 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 496 // Invoke chaincode 497 var retVal []byte 498 _, _, retVal, err = invoke(ctxt, chainID, spec2, nextBlockNumber, []byte("Alice")) 499 nextBlockNumber++ 500 501 if err != nil { 502 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 503 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 504 return fmt.Errorf("Error invoking <%s>: %s", ccID2, err) 505 } 506 507 // Check the return value 508 result, err := strconv.Atoi(string(retVal)) 509 if err != nil || result != 300 { 510 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 511 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 512 return fmt.Errorf("Incorrect final state after transaction for <%s>: %s", ccID1, err) 513 } 514 515 // Query second chaincode, which will inturn query the first chaincode 516 f = "query" 517 args = util.ToChaincodeArgs(f, ccID1, "sum") 518 519 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 520 // Invoke chaincode 521 _, _, retVal, err = invoke(ctxt, chainID, spec2, nextBlockNumber, []byte("Alice")) 522 523 if err != nil { 524 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 525 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 526 return fmt.Errorf("Error querying <%s>: %s", ccID2, err) 527 } 528 529 // Check the return value 530 result, err = strconv.Atoi(string(retVal)) 531 if err != nil || result != 300 { 532 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 533 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 534 return fmt.Errorf("Incorrect final value after query for <%s>: %s", ccID1, err) 535 } 536 537 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 538 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 539 540 return nil 541 } 542 543 // Check the correctness of the final state after transaction execution. 544 func checkFinalState(cccid *ccprovider.CCContext, a int, b int) error { 545 _, txsim, err := startTxSimulation(context.Background(), cccid.ChainID) 546 if err != nil { 547 return fmt.Errorf("Failed to get handle to simulator: %s ", err) 548 } 549 550 defer txsim.Done() 551 552 cName := cccid.GetCanonicalName() 553 554 // Invoke ledger to get state 555 var Aval, Bval int 556 resbytes, resErr := txsim.GetState(cccid.Name, "a") 557 if resErr != nil { 558 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 559 } 560 fmt.Printf("Got string: %s\n", string(resbytes)) 561 Aval, resErr = strconv.Atoi(string(resbytes)) 562 if resErr != nil { 563 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 564 } 565 if Aval != a { 566 return fmt.Errorf("Incorrect result. Aval %d != %d <%s>", Aval, a, cName) 567 } 568 569 resbytes, resErr = txsim.GetState(cccid.Name, "b") 570 if resErr != nil { 571 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 572 } 573 Bval, resErr = strconv.Atoi(string(resbytes)) 574 if resErr != nil { 575 return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr) 576 } 577 if Bval != b { 578 return fmt.Errorf("Incorrect result. Bval %d != %d <%s>", Bval, b, cName) 579 } 580 581 // Success 582 fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) 583 return nil 584 } 585 586 // Invoke chaincode_example02 587 func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContext, cID *pb.ChaincodeID, chaincodeType pb.ChaincodeSpec_Type, args []string, destroyImage bool) error { 588 // the ledger is created with genesis block. Start block number 1 onwards 589 var nextBlockNumber uint64 = 1 590 f := "init" 591 argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") 592 spec := &pb.ChaincodeSpec{Type: chaincodeType, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: argsDeploy}} 593 _, err := deploy(ctxt, cccid, spec, nextBlockNumber) 594 nextBlockNumber++ 595 ccID := spec.ChaincodeId.Name 596 if err != nil { 597 return fmt.Errorf("Error deploying <%s>: %s", ccID, err) 598 } 599 600 time.Sleep(time.Second) 601 602 if destroyImage { 603 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 604 dir := container.DestroyImageReq{CCID: ccintf.CCID{ChaincodeSpec: spec, NetworkID: theChaincodeSupport.peerNetworkID, PeerID: theChaincodeSupport.peerID, ChainID: cccid.ChainID}, Force: true, NoPrune: true} 605 606 _, err = container.VMCProcess(ctxt, container.DOCKER, dir) 607 if err != nil { 608 err = fmt.Errorf("Error destroying image: %s", err) 609 return err 610 } 611 } 612 613 f = "invoke" 614 invokeArgs := append([]string{f}, args...) 615 spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(invokeArgs...)}} 616 _, uuid, _, err := invoke(ctxt, cccid.ChainID, spec, nextBlockNumber, nil) 617 nextBlockNumber++ 618 if err != nil { 619 return fmt.Errorf("Error invoking <%s>: %s", cccid.Name, err) 620 } 621 622 cccid.TxID = uuid 623 err = checkFinalState(cccid, 90, 210) 624 if err != nil { 625 return fmt.Errorf("Incorrect final state after transaction for <%s>: %s", ccID, err) 626 } 627 628 // Test for delete state 629 f = "delete" 630 delArgs := util.ToChaincodeArgs(f, "a") 631 spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: delArgs}} 632 _, _, _, err = invoke(ctxt, cccid.ChainID, spec, nextBlockNumber, nil) 633 if err != nil { 634 return fmt.Errorf("Error deleting state in <%s>: %s", cccid.Name, err) 635 } 636 637 return nil 638 } 639 640 const ( 641 chaincodeExample02GolangPath = "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 642 chaincodeExample04GolangPath = "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example04" 643 chaincodeEventSenderGolangPath = "github.com/hyperledger/fabric/examples/chaincode/go/eventsender" 644 chaincodeExample02JavaPath = "../../examples/chaincode/java/chaincode_example02" 645 chaincodeExample04JavaPath = "../../examples/chaincode/java/chaincode_example04" 646 chaincodeExample06JavaPath = "../../examples/chaincode/java/chaincode_example06" 647 chaincodeEventSenderJavaPath = "../../examples/chaincode/java/eventsender" 648 ) 649 650 func runChaincodeInvokeChaincode(t *testing.T, channel1 string, channel2 string, tc tcicTc, cccid1 *ccprovider.CCContext, expectedA int, expectedB int, nextBlockNumber1, nextBlockNumber2 uint64) (uint64, uint64) { 651 var ctxt = context.Background() 652 653 // chaincode2: the chaincode that will call by chaincode1 654 chaincode2Name := generateChaincodeName(tc.chaincodeType) 655 chaincode2Version := "0" 656 chaincode2Type := tc.chaincodeType 657 chaincode2Path := tc.chaincodePath 658 chaincode2InitArgs := util.ToChaincodeArgs("init", "e", "0") 659 chaincode2Creator := []byte([]byte("Alice")) 660 661 // deploy second chaincode on channel1 662 _, cccid2, err := deployChaincode(ctxt, chaincode2Name, chaincode2Version, chaincode2Type, chaincode2Path, chaincode2InitArgs, chaincode2Creator, channel1, nextBlockNumber1) 663 if err != nil { 664 stopChaincode(ctxt, cccid1) 665 stopChaincode(ctxt, cccid2) 666 t.Fatalf("Error initializing chaincode %s(%s)", chaincode2Name, err) 667 return nextBlockNumber1, nextBlockNumber2 668 } 669 nextBlockNumber1++ 670 671 time.Sleep(time.Second) 672 673 // Invoke second chaincode passing the first chaincode's name as first param, 674 // which will inturn invoke the first chaincode 675 chaincode2InvokeSpec := &pb.ChaincodeSpec{ 676 Type: chaincode2Type, 677 ChaincodeId: &pb.ChaincodeID{ 678 Name: chaincode2Name, 679 Version: chaincode2Version, 680 }, 681 Input: &pb.ChaincodeInput{ 682 Args: util.ToChaincodeArgs("invoke", cccid1.Name, "e", "1"), 683 }, 684 } 685 // Invoke chaincode 686 _, txID, _, err := invoke(ctxt, channel1, chaincode2InvokeSpec, nextBlockNumber1, []byte("Alice")) 687 if err != nil { 688 stopChaincode(ctxt, cccid1) 689 stopChaincode(ctxt, cccid2) 690 t.Fatalf("Error invoking <%s>: %s", chaincode2Name, err) 691 return nextBlockNumber1, nextBlockNumber2 692 } 693 nextBlockNumber1++ 694 695 // TODO this doesn't seeem to be used, remove? 696 cccid1.TxID = txID 697 698 // Check the state in the ledger 699 err = checkFinalState(cccid1, expectedA, expectedB) 700 if err != nil { 701 stopChaincode(ctxt, cccid1) 702 stopChaincode(ctxt, cccid2) 703 t.Fatalf("Incorrect final state after transaction for <%s>: %s", cccid1.Name, err) 704 return nextBlockNumber1, nextBlockNumber2 705 } 706 707 // Change the policies of the two channels in such a way: 708 // 1. Alice has reader access to both the channels. 709 // 2. Bob has access only to chainID2. 710 // Therefore the chaincode invocation should fail. 711 pm := peer.GetPolicyManager(channel1) 712 pm.(*mockpolicies.Manager).PolicyMap = map[string]policies.Policy{ 713 policies.ChannelApplicationWriters: &CreatorPolicy{Creators: [][]byte{[]byte("Alice")}}, 714 } 715 716 pm = peer.GetPolicyManager(channel2) 717 pm.(*mockpolicies.Manager).PolicyMap = map[string]policies.Policy{ 718 policies.ChannelApplicationWriters: &CreatorPolicy{Creators: [][]byte{[]byte("Alice"), []byte("Bob")}}, 719 } 720 721 // deploy chaincode2 on channel2 722 _, cccid3, err := deployChaincode(ctxt, chaincode2Name, chaincode2Version, chaincode2Type, chaincode2Path, chaincode2InitArgs, chaincode2Creator, channel2, nextBlockNumber2) 723 if err != nil { 724 stopChaincode(ctxt, cccid1) 725 stopChaincode(ctxt, cccid2) 726 stopChaincode(ctxt, cccid3) 727 t.Fatalf("Error initializing chaincode %s/%s: %s", chaincode2Name, channel2, err) 728 return nextBlockNumber1, nextBlockNumber2 729 } 730 nextBlockNumber2++ 731 time.Sleep(time.Second) 732 733 // as Bob, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel1 734 chaincode2InvokeSpec = &pb.ChaincodeSpec{ 735 Type: chaincode2Type, 736 ChaincodeId: &pb.ChaincodeID{ 737 Name: chaincode2Name, 738 Version: chaincode2Version, 739 }, 740 Input: &pb.ChaincodeInput{ 741 Args: util.ToChaincodeArgs("invoke", cccid1.Name, "e", "1", channel1), 742 }, 743 } 744 _, _, _, err = invoke(ctxt, channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Bob")) 745 if err == nil { 746 // Bob should not be able to call 747 stopChaincode(ctxt, cccid1) 748 stopChaincode(ctxt, cccid2) 749 stopChaincode(ctxt, cccid3) 750 nextBlockNumber2++ 751 t.Fatalf("As Bob, invoking <%s/%s> via <%s/%s> should fail, but it succeeded.", cccid1.Name, cccid1.ChainID, chaincode2Name, channel2) 752 return nextBlockNumber1, nextBlockNumber2 753 } 754 755 // as Alice, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel1 756 _, _, _, err = invoke(ctxt, channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Alice")) 757 if err != nil { 758 // Alice should be able to call 759 stopChaincode(ctxt, cccid1) 760 stopChaincode(ctxt, cccid2) 761 stopChaincode(ctxt, cccid3) 762 t.Fatalf("As Alice, invoking <%s/%s> via <%s/%s> should should of succeeded, but it failed: %s", cccid1.Name, cccid1.ChainID, chaincode2Name, channel2, err) 763 return nextBlockNumber1, nextBlockNumber2 764 } 765 nextBlockNumber2++ 766 767 stopChaincode(ctxt, cccid1) 768 stopChaincode(ctxt, cccid2) 769 stopChaincode(ctxt, cccid3) 770 771 return nextBlockNumber1, nextBlockNumber2 772 } 773 774 // Test deploy of a transaction 775 func TestExecuteDeployTransaction(t *testing.T) { 776 //chaincoe is deployed as part of many tests. No need for a separate one for this 777 t.Skip() 778 chainID := util.GetTestChainID() 779 780 executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01") 781 } 782 783 // Test deploy of a transaction with a GOPATH with multiple elements 784 func TestGopathExecuteDeployTransaction(t *testing.T) { 785 //this is no longer critical as chaincode is assembled in the client side (SDK) 786 t.Skip() 787 chainID := util.GetTestChainID() 788 789 // add a trailing slash to GOPATH 790 // and a couple of elements - it doesn't matter what they are 791 os.Setenv("GOPATH", os.Getenv("GOPATH")+string(os.PathSeparator)+string(os.PathListSeparator)+"/tmp/foo"+string(os.PathListSeparator)+"/tmp/bar") 792 executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01") 793 } 794 795 func TestExecuteInvokeTransaction(t *testing.T) { 796 testForSkip(t) 797 798 testCases := []struct { 799 chaincodeType pb.ChaincodeSpec_Type 800 chaincodePath string 801 }{ 802 {pb.ChaincodeSpec_GOLANG, chaincodeExample02GolangPath}, 803 {pb.ChaincodeSpec_JAVA, chaincodeExample02JavaPath}, 804 } 805 806 for _, tc := range testCases { 807 t.Run(tc.chaincodeType.String(), func(t *testing.T) { 808 809 if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" { 810 t.Skip("No Java chaincode support yet on non-x86_64.") 811 } 812 813 chainID := util.GetTestChainID() 814 815 lis, err := initPeer(chainID) 816 if err != nil { 817 t.Fail() 818 t.Logf("Error creating peer: %s", err) 819 } 820 821 defer finitPeer(lis, chainID) 822 823 var ctxt = context.Background() 824 chaincodeName := generateChaincodeName(tc.chaincodeType) 825 chaincodeVersion := "1.0.0.0" 826 cccid := ccprovider.NewCCContext(chainID, chaincodeName, chaincodeVersion, "", false, nil, nil) 827 ccID := &pb.ChaincodeID{Name: chaincodeName, Path: tc.chaincodePath, Version: chaincodeVersion} 828 829 args := []string{"a", "b", "10"} 830 err = invokeExample02Transaction(ctxt, cccid, ccID, tc.chaincodeType, args, true) 831 if err != nil { 832 t.Fail() 833 t.Logf("Error invoking transaction: %s", err) 834 } else { 835 fmt.Print("Invoke test passed\n") 836 t.Log("Invoke test passed") 837 } 838 839 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}}) 840 841 }) 842 } 843 844 } 845 846 // Test the execution of an invalid transaction. 847 func TestExecuteInvokeInvalidTransaction(t *testing.T) { 848 testForSkip(t) 849 850 chainID := util.GetTestChainID() 851 852 lis, err := initPeer(chainID) 853 if err != nil { 854 t.Fail() 855 t.Logf("Error creating peer: %s", err) 856 } 857 858 defer finitPeer(lis, chainID) 859 860 var ctxt = context.Background() 861 862 url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 863 ccID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"} 864 865 cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil) 866 867 //FAIL, FAIL! 868 args := []string{"x", "-1"} 869 err = invokeExample02Transaction(ctxt, cccid, ccID, pb.ChaincodeSpec_GOLANG, args, false) 870 871 //this HAS to fail with expectedDeltaStringPrefix 872 if err != nil { 873 errStr := err.Error() 874 t.Logf("Got error %s\n", errStr) 875 t.Log("InvalidInvoke test passed") 876 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}}) 877 878 return 879 } 880 881 t.Fail() 882 t.Logf("Error invoking transaction %s", err) 883 884 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}}) 885 } 886 887 // testcase parameters for TestChaincodeInvokeChaincode 888 type tcicTc struct { 889 chaincodeType pb.ChaincodeSpec_Type 890 chaincodePath string 891 } 892 893 // Test the execution of a chaincode that invokes another chaincode. 894 func TestChaincodeInvokeChaincode(t *testing.T) { 895 testForSkip(t) 896 channel := util.GetTestChainID() 897 channel2 := channel + "2" 898 lis, err := initPeer(channel, channel2) 899 if err != nil { 900 t.Fail() 901 t.Logf("Error creating peer: %s", err) 902 } 903 904 defer finitPeer(lis, channel, channel2) 905 906 testCases := []tcicTc{ 907 {pb.ChaincodeSpec_GOLANG, chaincodeExample04GolangPath}, 908 {pb.ChaincodeSpec_JAVA, chaincodeExample04JavaPath}, 909 } 910 911 ctx := context.Background() 912 913 var nextBlockNumber1 uint64 = 1 914 var nextBlockNumber2 uint64 = 1 915 916 // deploy the chaincode that will be called by the second chaincode 917 chaincode1Name := generateChaincodeName(pb.ChaincodeSpec_GOLANG) 918 chaincode1Version := "0" 919 chaincode1Type := pb.ChaincodeSpec_GOLANG 920 chaincode1Path := chaincodeExample02GolangPath 921 initialA := 100 922 initialB := 200 923 chaincode1InitArgs := util.ToChaincodeArgs("init", "a", strconv.Itoa(initialA), "b", strconv.Itoa(initialB)) 924 chaincode1Creator := []byte([]byte("Alice")) 925 926 // Deploy first chaincode 927 _, chaincodeCtx, err := deployChaincode(ctx, chaincode1Name, chaincode1Version, chaincode1Type, chaincode1Path, chaincode1InitArgs, chaincode1Creator, channel, nextBlockNumber1) 928 if err != nil { 929 stopChaincode(ctx, chaincodeCtx) 930 t.Fatalf("Error initializing chaincode %s: %s", chaincodeCtx.Name, err) 931 } 932 nextBlockNumber1++ 933 time.Sleep(time.Second) 934 935 expectedA := initialA 936 expectedB := initialB 937 938 for _, tc := range testCases { 939 t.Run(tc.chaincodeType.String(), func(t *testing.T) { 940 941 if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" { 942 t.Skip("No Java chaincode support yet on non-x86_64.") 943 } 944 945 expectedA = expectedA - 10 946 expectedB = expectedB + 10 947 nextBlockNumber1, nextBlockNumber2 = runChaincodeInvokeChaincode(t, channel, channel2, tc, chaincodeCtx, expectedA, expectedB, nextBlockNumber1, nextBlockNumber2) 948 }) 949 } 950 951 closeListenerAndSleep(lis) 952 } 953 954 func stopChaincode(ctx context.Context, chaincodeCtx *ccprovider.CCContext) { 955 theChaincodeSupport.Stop(ctx, chaincodeCtx, 956 &pb.ChaincodeDeploymentSpec{ 957 ChaincodeSpec: &pb.ChaincodeSpec{ 958 ChaincodeId: &pb.ChaincodeID{ 959 Name: chaincodeCtx.Name, 960 Version: chaincodeCtx.Version, 961 }, 962 }, 963 }) 964 } 965 966 // Test the execution of a chaincode that invokes another chaincode with wrong parameters. Should receive error from 967 // from the called chaincode 968 func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { 969 testForSkip(t) 970 chainID := util.GetTestChainID() 971 972 lis, err := initPeer(chainID) 973 if err != nil { 974 t.Fail() 975 t.Logf("Error creating peer: %s", err) 976 } 977 978 defer finitPeer(lis, chainID) 979 980 var ctxt = context.Background() 981 982 // Deploy first chaincode 983 url1 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 984 985 cID1 := &pb.ChaincodeID{Name: "example02", Path: url1, Version: "0"} 986 f := "init" 987 args := util.ToChaincodeArgs(f, "a", "100", "b", "200") 988 989 spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} 990 991 sProp, prop := putils.MockSignedEndorserProposalOrPanic(util.GetTestChainID(), spec1, []byte([]byte("Alice")), nil) 992 cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, sProp, prop) 993 994 var nextBlockNumber uint64 = 1 995 996 _, err = deploy(ctxt, cccid1, spec1, nextBlockNumber) 997 nextBlockNumber++ 998 ccID1 := spec1.ChaincodeId.Name 999 if err != nil { 1000 t.Fail() 1001 t.Logf("Error initializing chaincode %s(%s)", ccID1, err) 1002 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1003 return 1004 } 1005 1006 time.Sleep(time.Second) 1007 1008 // Deploy second chaincode 1009 url2 := "github.com/hyperledger/fabric/examples/chaincode/go/passthru" 1010 1011 cID2 := &pb.ChaincodeID{Name: "pthru", Path: url2, Version: "0"} 1012 f = "init" 1013 args = util.ToChaincodeArgs(f) 1014 1015 spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 1016 1017 cccid2 := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, sProp, prop) 1018 1019 _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) 1020 nextBlockNumber++ 1021 ccID2 := spec2.ChaincodeId.Name 1022 if err != nil { 1023 t.Fail() 1024 t.Logf("Error initializing chaincode %s(%s)", ccID2, err) 1025 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1026 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1027 return 1028 } 1029 1030 time.Sleep(time.Second) 1031 1032 // Invoke second chaincode, which will inturn invoke the first chaincode but pass bad params 1033 f = ccID1 1034 args = util.ToChaincodeArgs(f, "invoke", "a") 1035 1036 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 1037 // Invoke chaincode 1038 _, _, _, err = invoke(ctxt, chainID, spec2, nextBlockNumber, []byte("Alice")) 1039 1040 if err == nil { 1041 t.Fail() 1042 t.Logf("Error invoking <%s>: %s", ccID2, err) 1043 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1044 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1045 return 1046 } 1047 1048 if strings.Index(err.Error(), "Error invoking chaincode: Incorrect number of arguments. Expecting 3") < 0 { 1049 t.Fail() 1050 t.Logf("Unexpected error %s", err) 1051 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1052 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1053 return 1054 } 1055 1056 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1057 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1058 } 1059 1060 // Test the invocation of a transaction. 1061 func TestQueries(t *testing.T) { 1062 testForSkip(t) 1063 1064 chainID := util.GetTestChainID() 1065 1066 lis, err := initPeer(chainID) 1067 if err != nil { 1068 t.Fail() 1069 t.Logf("Error creating peer: %s", err) 1070 } 1071 1072 defer finitPeer(lis, chainID) 1073 1074 var ctxt = context.Background() 1075 1076 url := "github.com/hyperledger/fabric/examples/chaincode/go/map" 1077 cID := &pb.ChaincodeID{Name: "tmap", Path: url, Version: "0"} 1078 1079 f := "init" 1080 args := util.ToChaincodeArgs(f) 1081 1082 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1083 1084 cccid := ccprovider.NewCCContext(chainID, "tmap", "0", "", false, nil, nil) 1085 1086 var nextBlockNumber uint64 = 1 1087 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) 1088 nextBlockNumber++ 1089 ccID := spec.ChaincodeId.Name 1090 if err != nil { 1091 t.Fail() 1092 t.Logf("Error initializing chaincode %s(%s)", ccID, err) 1093 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1094 return 1095 } 1096 1097 // Add 101 marbles for testing range queries and rich queries (for capable ledgers) 1098 // The tests will test both range and rich queries and queries with query limits 1099 for i := 1; i <= 101; i++ { 1100 f = "put" 1101 1102 // 51 owned by tom, 50 by jerry 1103 owner := "tom" 1104 if i%2 == 0 { 1105 owner = "jerry" 1106 } 1107 1108 // one marble color is red, 100 are blue 1109 color := "blue" 1110 if i == 12 { 1111 color = "red" 1112 } 1113 1114 key := fmt.Sprintf("marble%03d", i) 1115 argsString := fmt.Sprintf("{\"docType\":\"marble\",\"name\":\"%s\",\"color\":\"%s\",\"size\":35,\"owner\":\"%s\"}", key, color, owner) 1116 args = util.ToChaincodeArgs(f, key, argsString) 1117 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1118 _, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1119 nextBlockNumber++ 1120 1121 if err != nil { 1122 t.Fail() 1123 t.Logf("Error invoking <%s>: %s", ccID, err) 1124 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1125 return 1126 } 1127 } 1128 1129 //The following range query for "marble001" to "marble011" should return 10 marbles 1130 f = "keys" 1131 args = util.ToChaincodeArgs(f, "marble001", "marble011") 1132 1133 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1134 _, _, retval, err := invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1135 nextBlockNumber++ 1136 if err != nil { 1137 t.Fail() 1138 t.Logf("Error invoking <%s>: %s", ccID, err) 1139 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1140 return 1141 } 1142 1143 var keys []interface{} 1144 err = json.Unmarshal(retval, &keys) 1145 if len(keys) != 10 { 1146 t.Fail() 1147 t.Logf("Error detected with the range query, should have returned 10 but returned %v", len(keys)) 1148 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1149 return 1150 } 1151 1152 //FAB-1163- The following range query should timeout and produce an error 1153 //the peer should handle this gracefully and not die 1154 1155 //save the original timeout and set a new timeout of 1 sec 1156 origTimeout := theChaincodeSupport.executetimeout 1157 theChaincodeSupport.executetimeout = time.Duration(1) * time.Second 1158 1159 //chaincode to sleep for 2 secs with timeout 1 1160 args = util.ToChaincodeArgs(f, "marble001", "marble002", "2000") 1161 1162 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1163 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1164 if err == nil { 1165 t.Fail() 1166 t.Logf("expected timeout error but succeeded") 1167 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1168 return 1169 } 1170 1171 //restore timeout 1172 theChaincodeSupport.executetimeout = origTimeout 1173 1174 // querying for all marbles will return 101 marbles 1175 // this query should return exactly 101 results (one call to Next()) 1176 //The following range query for "marble001" to "marble102" should return 101 marbles 1177 f = "keys" 1178 args = util.ToChaincodeArgs(f, "marble001", "marble102") 1179 1180 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1181 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1182 nextBlockNumber++ 1183 if err != nil { 1184 t.Fail() 1185 t.Logf("Error invoking <%s>: %s", ccID, err) 1186 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1187 return 1188 } 1189 1190 //unmarshal the results 1191 err = json.Unmarshal(retval, &keys) 1192 1193 //check to see if there are 101 values 1194 //default query limit of 10000 is used, this query is effectively unlimited 1195 if len(keys) != 101 { 1196 t.Fail() 1197 t.Logf("Error detected with the range query, should have returned 101 but returned %v", len(keys)) 1198 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1199 return 1200 } 1201 1202 // querying for all simple key. This query should return exactly 101 simple keys (one 1203 // call to Next()) no composite keys. 1204 //The following open ended range query for "" to "" should return 101 marbles 1205 f = "keys" 1206 args = util.ToChaincodeArgs(f, "", "") 1207 1208 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1209 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1210 nextBlockNumber++ 1211 if err != nil { 1212 t.Fail() 1213 t.Logf("Error invoking <%s>: %s", ccID, err) 1214 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1215 return 1216 } 1217 1218 //unmarshal the results 1219 err = json.Unmarshal(retval, &keys) 1220 1221 //check to see if there are 101 values 1222 //default query limit of 10000 is used, this query is effectively unlimited 1223 if len(keys) != 101 { 1224 t.Fail() 1225 t.Logf("Error detected with the range query, should have returned 101 but returned %v", len(keys)) 1226 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1227 return 1228 } 1229 1230 // ExecuteQuery supported only for CouchDB and 1231 // query limits apply for CouchDB range and rich queries only 1232 if ledgerconfig.IsCouchDBEnabled() == true { 1233 1234 // corner cases for shim batching. currnt shim batch size is 100 1235 // this query should return exactly 100 results (no call to Next()) 1236 f = "query" 1237 args = util.ToChaincodeArgs(f, "{\"selector\":{\"color\":\"blue\"}}") 1238 1239 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1240 _, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1241 nextBlockNumber++ 1242 1243 if err != nil { 1244 t.Fail() 1245 t.Logf("Error invoking <%s>: %s", ccID, err) 1246 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1247 return 1248 } 1249 1250 //unmarshal the results 1251 err = json.Unmarshal(retval, &keys) 1252 1253 //check to see if there are 100 values 1254 if len(keys) != 100 { 1255 t.Fail() 1256 t.Logf("Error detected with the rich query, should have returned 100 but returned %v %s", len(keys), keys) 1257 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1258 return 1259 } 1260 1261 //Reset the query limit to 5 1262 viper.Set("ledger.state.queryLimit", 5) 1263 1264 //The following range query for "marble01" to "marble11" should return 5 marbles due to the queryLimit 1265 f = "keys" 1266 args = util.ToChaincodeArgs(f, "marble001", "marble011") 1267 1268 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1269 _, _, retval, err := invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1270 nextBlockNumber++ 1271 if err != nil { 1272 t.Fail() 1273 t.Logf("Error invoking <%s>: %s", ccID, err) 1274 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1275 return 1276 } 1277 1278 //unmarshal the results 1279 err = json.Unmarshal(retval, &keys) 1280 1281 //check to see if there are 5 values 1282 if len(keys) != 5 { 1283 t.Fail() 1284 t.Logf("Error detected with the range query, should have returned 5 but returned %v", len(keys)) 1285 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1286 return 1287 } 1288 1289 //Reset the query limit to 10000 1290 viper.Set("ledger.state.queryLimit", 10000) 1291 1292 //The following rich query for should return 50 marbles 1293 f = "query" 1294 args = util.ToChaincodeArgs(f, "{\"selector\":{\"owner\":\"jerry\"}}") 1295 1296 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1297 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1298 nextBlockNumber++ 1299 1300 if err != nil { 1301 t.Fail() 1302 t.Logf("Error invoking <%s>: %s", ccID, err) 1303 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1304 return 1305 } 1306 1307 //unmarshal the results 1308 err = json.Unmarshal(retval, &keys) 1309 1310 //check to see if there are 50 values 1311 //default query limit of 10000 is used, this query is effectively unlimited 1312 if len(keys) != 50 { 1313 t.Fail() 1314 t.Logf("Error detected with the rich query, should have returned 50 but returned %v", len(keys)) 1315 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1316 return 1317 } 1318 1319 //Reset the query limit to 5 1320 viper.Set("ledger.state.queryLimit", 5) 1321 1322 //The following rich query should return 5 marbles due to the queryLimit 1323 f = "query" 1324 args = util.ToChaincodeArgs(f, "{\"selector\":{\"owner\":\"jerry\"}}") 1325 1326 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1327 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1328 nextBlockNumber++ 1329 if err != nil { 1330 t.Fail() 1331 t.Logf("Error invoking <%s>: %s", ccID, err) 1332 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1333 return 1334 } 1335 1336 //unmarshal the results 1337 err = json.Unmarshal(retval, &keys) 1338 1339 //check to see if there are 5 values 1340 if len(keys) != 5 { 1341 t.Fail() 1342 t.Logf("Error detected with the rich query, should have returned 5 but returned %v", len(keys)) 1343 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1344 return 1345 } 1346 1347 } 1348 1349 // modifications for history query 1350 f = "put" 1351 args = util.ToChaincodeArgs(f, "marble012", "{\"docType\":\"marble\",\"name\":\"marble012\",\"color\":\"red\",\"size\":30,\"owner\":\"jerry\"}") 1352 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1353 _, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1354 nextBlockNumber++ 1355 if err != nil { 1356 t.Fail() 1357 t.Logf("Error invoking <%s>: %s", ccID, err) 1358 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1359 return 1360 } 1361 1362 f = "put" 1363 args = util.ToChaincodeArgs(f, "marble012", "{\"docType\":\"marble\",\"name\":\"marble012\",\"color\":\"red\",\"size\":30,\"owner\":\"jerry\"}") 1364 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1365 _, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1366 nextBlockNumber++ 1367 if err != nil { 1368 t.Fail() 1369 t.Logf("Error invoking <%s>: %s", ccID, err) 1370 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1371 return 1372 } 1373 1374 //The following history query for "marble12" should return 3 records 1375 f = "history" 1376 args = util.ToChaincodeArgs(f, "marble012") 1377 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1378 _, _, retval, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1379 nextBlockNumber++ 1380 if err != nil { 1381 t.Fail() 1382 t.Logf("Error invoking <%s>: %s", ccID, err) 1383 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1384 return 1385 } 1386 1387 var history []interface{} 1388 err = json.Unmarshal(retval, &history) 1389 if len(history) != 3 { 1390 t.Fail() 1391 t.Logf("Error detected with the history query, should have returned 3 but returned %v", len(keys)) 1392 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1393 return 1394 } 1395 1396 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1397 } 1398 1399 func TestGetEvent(t *testing.T) { 1400 testForSkip(t) 1401 testCases := []struct { 1402 chaincodeType pb.ChaincodeSpec_Type 1403 chaincodePath string 1404 }{ 1405 {pb.ChaincodeSpec_GOLANG, chaincodeEventSenderGolangPath}, 1406 {pb.ChaincodeSpec_JAVA, chaincodeEventSenderJavaPath}, 1407 } 1408 1409 chainID := util.GetTestChainID() 1410 var nextBlockNumber uint64 1411 1412 lis, err := initPeer(chainID) 1413 if err != nil { 1414 t.Fail() 1415 t.Logf("Error creating peer: %s", err) 1416 } 1417 1418 nextBlockNumber++ 1419 1420 defer finitPeer(lis, chainID) 1421 1422 for _, tc := range testCases { 1423 t.Run(tc.chaincodeType.String(), func(t *testing.T) { 1424 1425 if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" { 1426 t.Skip("No Java chaincode support yet on non-x86_64.") 1427 } 1428 1429 var ctxt = context.Background() 1430 1431 cID := &pb.ChaincodeID{Name: generateChaincodeName(tc.chaincodeType), Path: tc.chaincodePath, Version: "0"} 1432 f := "init" 1433 spec := &pb.ChaincodeSpec{Type: tc.chaincodeType, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(f)}} 1434 1435 cccid := ccprovider.NewCCContext(chainID, cID.Name, cID.Version, "", false, nil, nil) 1436 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) 1437 nextBlockNumber++ 1438 ccID := spec.ChaincodeId.Name 1439 if err != nil { 1440 t.Fail() 1441 t.Logf("Error initializing chaincode %s(%s)", ccID, err) 1442 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1443 return 1444 } 1445 1446 time.Sleep(time.Second) 1447 1448 args := util.ToChaincodeArgs("invoke", "i", "am", "satoshi") 1449 1450 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1451 1452 var ccevt *pb.ChaincodeEvent 1453 ccevt, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1454 nextBlockNumber++ 1455 1456 if err != nil { 1457 t.Logf("Error invoking chaincode %s(%s)", ccID, err) 1458 t.Fail() 1459 } 1460 1461 if ccevt == nil { 1462 t.Logf("Error ccevt is nil %s(%s)", ccID, err) 1463 t.Fail() 1464 } 1465 1466 if ccevt.ChaincodeId != ccID { 1467 t.Logf("Error ccevt id(%s) != cid(%s)", ccevt.ChaincodeId, ccID) 1468 t.Fail() 1469 } 1470 1471 if strings.Index(string(ccevt.Payload), "i,am,satoshi") < 0 { 1472 t.Logf("Error expected event not found (%s)", string(ccevt.Payload)) 1473 t.Fail() 1474 } 1475 1476 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1477 }) 1478 } 1479 1480 } 1481 1482 // Test the execution of a chaincode that queries another chaincode 1483 // example02 implements "query" as a function in Invoke. example05 calls example02 1484 func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { 1485 testForSkip(t) 1486 //this is essentially same as the ChaincodeInvokeChaincode now that 1487 //we don't distinguish between Invoke and Query (there's no separate "Query") 1488 t.Skip() 1489 chainID := util.GetTestChainID() 1490 1491 var peerLis net.Listener 1492 var err error 1493 if peerLis, err = initPeer(chainID); err != nil { 1494 t.Fail() 1495 t.Logf("Error registering user %s", err) 1496 return 1497 } 1498 1499 defer finitPeer(peerLis, chainID) 1500 1501 var ctxt = context.Background() 1502 1503 // Deploy first chaincode 1504 url1 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" 1505 1506 cID1 := &pb.ChaincodeID{Name: "example02", Path: url1, Version: "0"} 1507 f := "init" 1508 args := util.ToChaincodeArgs(f, "a", "100", "b", "200") 1509 1510 spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID1, Input: &pb.ChaincodeInput{Args: args}} 1511 1512 sProp, prop := putils.MockSignedEndorserProposalOrPanic(util.GetTestChainID(), spec1, []byte([]byte("Alice")), nil) 1513 cccid1 := ccprovider.NewCCContext(chainID, "example02", "0", "", false, sProp, prop) 1514 var nextBlockNumber uint64 1515 _, err = deploy(ctxt, cccid1, spec1, nextBlockNumber) 1516 nextBlockNumber++ 1517 ccID1 := spec1.ChaincodeId.Name 1518 if err != nil { 1519 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1520 t.Fail() 1521 t.Logf("Error initializing chaincode %s(%s)", ccID1, err) 1522 return 1523 } 1524 1525 time.Sleep(time.Second) 1526 1527 // Deploy second chaincode 1528 url2 := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example05" 1529 1530 cID2 := &pb.ChaincodeID{Name: "example05", Path: url2, Version: "0"} 1531 f = "init" 1532 args = util.ToChaincodeArgs(f, "sum", "0") 1533 1534 spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 1535 1536 cccid2 := ccprovider.NewCCContext(chainID, "example05", "0", "", false, sProp, prop) 1537 1538 _, err = deploy(ctxt, cccid2, spec2, nextBlockNumber) 1539 nextBlockNumber++ 1540 ccID2 := spec2.ChaincodeId.Name 1541 if err != nil { 1542 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1543 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1544 t.Fail() 1545 t.Logf("Error initializing chaincode %s(%s)", ccID2, err) 1546 return 1547 } 1548 1549 time.Sleep(time.Second) 1550 1551 // Invoke second chaincode, which will inturn query the first chaincode 1552 f = "invoke" 1553 args = util.ToChaincodeArgs(f, ccID1, "sum") 1554 1555 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 1556 // Invoke chaincode 1557 var retVal []byte 1558 _, _, retVal, err = invoke(ctxt, chainID, spec2, nextBlockNumber, []byte("Alice")) 1559 nextBlockNumber++ 1560 if err != nil { 1561 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1562 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1563 t.Fail() 1564 t.Logf("Error invoking <%s>: %s", ccID2, err) 1565 return 1566 } 1567 1568 // Check the return value 1569 result, err := strconv.Atoi(string(retVal)) 1570 if err != nil || result != 300 { 1571 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1572 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1573 t.Fail() 1574 t.Logf("Incorrect final state after transaction for <%s>: %s", ccID1, err) 1575 return 1576 } 1577 1578 // Query second chaincode, which will inturn query the first chaincode 1579 f = "query" 1580 args = util.ToChaincodeArgs(f, ccID1, "sum") 1581 1582 spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID2, Input: &pb.ChaincodeInput{Args: args}} 1583 // Invoke chaincode 1584 _, _, retVal, err = invoke(ctxt, chainID, spec2, nextBlockNumber, []byte("Alice")) 1585 1586 if err != nil { 1587 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1588 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1589 t.Fail() 1590 t.Logf("Error querying <%s>: %s", ccID2, err) 1591 return 1592 } 1593 1594 // Check the return value 1595 result, err = strconv.Atoi(string(retVal)) 1596 if err != nil || result != 300 { 1597 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1598 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1599 t.Fail() 1600 t.Logf("Incorrect final value after query for <%s>: %s", ccID1, err) 1601 return 1602 } 1603 1604 theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) 1605 theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) 1606 } 1607 1608 // test that invoking a security-sensitive system chaincode fails 1609 func TestChaincodeInvokesForbiddenSystemChaincode(t *testing.T) { 1610 testForSkip(t) 1611 chainID := util.GetTestChainID() 1612 1613 lis, err := initPeer(chainID) 1614 if err != nil { 1615 t.Fail() 1616 t.Logf("Error creating peer: %s", err) 1617 } 1618 1619 defer finitPeer(lis, chainID) 1620 1621 var ctxt = context.Background() 1622 1623 var nextBlockNumber uint64 = 1 1624 1625 // Deploy second chaincode 1626 url := "github.com/hyperledger/fabric/examples/chaincode/go/passthru" 1627 1628 cID := &pb.ChaincodeID{Name: "pthru", Path: url, Version: "0"} 1629 f := "init" 1630 args := util.ToChaincodeArgs(f) 1631 1632 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1633 1634 cccid := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil, nil) 1635 1636 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) 1637 nextBlockNumber++ 1638 ccID := spec.ChaincodeId.Name 1639 if err != nil { 1640 t.Fail() 1641 t.Logf("Error initializing chaincode %s(%s)", ccID, err) 1642 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1643 return 1644 } 1645 1646 time.Sleep(time.Second) 1647 1648 // send an invoke to pass thru to invoke "escc" system chaincode 1649 // this should fail 1650 args = util.ToChaincodeArgs("escc/"+chainID, "getid", chainID, "pthru") 1651 1652 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1653 // Invoke chaincode 1654 _, _, _, err = invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1655 if err == nil { 1656 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1657 t.Logf("invoking <%s> should have failed", ccID) 1658 t.Fail() 1659 return 1660 } 1661 } 1662 1663 // Test the execution of a chaincode that invokes system chaincode 1664 // uses the "pthru" chaincode to query "lscc" for the "pthru" chaincode 1665 func TestChaincodeInvokesSystemChaincode(t *testing.T) { 1666 testForSkip(t) 1667 chainID := util.GetTestChainID() 1668 1669 lis, err := initPeer(chainID) 1670 if err != nil { 1671 t.Fail() 1672 t.Logf("Error creating peer: %s", err) 1673 } 1674 1675 defer finitPeer(lis, chainID) 1676 1677 var ctxt = context.Background() 1678 1679 var nextBlockNumber uint64 = 1 1680 1681 // Deploy second chaincode 1682 url := "github.com/hyperledger/fabric/examples/chaincode/go/passthru" 1683 1684 cID := &pb.ChaincodeID{Name: "pthru", Path: url, Version: "0"} 1685 f := "init" 1686 args := util.ToChaincodeArgs(f) 1687 1688 spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1689 1690 cccid := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil, nil) 1691 1692 _, err = deploy(ctxt, cccid, spec, nextBlockNumber) 1693 nextBlockNumber++ 1694 ccID := spec.ChaincodeId.Name 1695 if err != nil { 1696 t.Fail() 1697 t.Logf("Error initializing chaincode %s(%s)", ccID, err) 1698 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1699 return 1700 } 1701 1702 time.Sleep(time.Second) 1703 1704 //send an invoke to pass thru to query "lscc" system chaincode on chainID to get 1705 //information about "pthru" 1706 args = util.ToChaincodeArgs("lscc/"+chainID, "getid", chainID, "pthru") 1707 1708 spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}} 1709 // Invoke chaincode 1710 _, _, retval, err := invoke(ctxt, chainID, spec, nextBlockNumber, nil) 1711 1712 if err != nil { 1713 t.Fail() 1714 t.Logf("Error invoking <%s>: %s", ccID, err) 1715 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1716 return 1717 } 1718 1719 if string(retval) != "pthru" { 1720 t.Fail() 1721 t.Logf("Expected to get back \"pthru\" from lscc but got back %s", string(retval)) 1722 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1723 return 1724 } 1725 1726 theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) 1727 } 1728 1729 func TestChaincodeInitializeInitError(t *testing.T) { 1730 testForSkip(t) 1731 testCases := []struct { 1732 name string 1733 chaincodeType pb.ChaincodeSpec_Type 1734 chaincodePath string 1735 args []string 1736 }{ 1737 {"NotSuccessResponse", pb.ChaincodeSpec_GOLANG, chaincodeExample02GolangPath, []string{"init", "not", "enough", "args"}}, 1738 {"NotSuccessResponse", pb.ChaincodeSpec_JAVA, chaincodeExample02JavaPath, []string{"init", "not", "enough", "args"}}, 1739 {"RuntimeException", pb.ChaincodeSpec_JAVA, chaincodeExample06JavaPath, []string{"runtimeException"}}, 1740 } 1741 1742 channel := util.GetTestChainID() 1743 1744 for _, tc := range testCases { 1745 t.Run(tc.name+"_"+tc.chaincodeType.String(), func(t *testing.T) { 1746 1747 if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" { 1748 t.Skip("No Java chaincode support yet on non-x86_64.") 1749 } 1750 1751 // initialize peer 1752 if listener, err := initPeer(channel); err != nil { 1753 t.Errorf("Error creating peer: %s", err) 1754 } else { 1755 defer finitPeer(listener, channel) 1756 } 1757 1758 var nextBlockNumber uint64 1759 1760 // the chaincode to install and instanciate 1761 chaincodeName := generateChaincodeName(tc.chaincodeType) 1762 chaincodePath := tc.chaincodePath 1763 chaincodeVersion := "1.0.0.0" 1764 chaincodeType := tc.chaincodeType 1765 chaincodeDeployArgs := util.ArrayToChaincodeArgs(tc.args) 1766 1767 // attempt to deploy chaincode 1768 _, chaincodeCtx, err := deployChaincode(context.Background(), chaincodeName, chaincodeVersion, chaincodeType, chaincodePath, chaincodeDeployArgs, nil, channel, nextBlockNumber) 1769 1770 // deploy should of failed 1771 if err == nil { 1772 stopChaincode(context.Background(), chaincodeCtx) 1773 t.Fatal("Deployment should have failed.") 1774 } 1775 t.Log(err) 1776 1777 }) 1778 } 1779 } 1780 1781 func TestMain(m *testing.M) { 1782 var err error 1783 1784 msptesttools.LoadMSPSetupForTesting() 1785 signer, err = mspmgmt.GetLocalMSP().GetDefaultSigningIdentity() 1786 if err != nil { 1787 fmt.Print("Could not initialize msp/signer") 1788 os.Exit(-1) 1789 return 1790 } 1791 1792 setupTestConfig() 1793 os.Exit(m.Run()) 1794 } 1795 1796 func setupTestConfig() { 1797 flag.Parse() 1798 1799 // Now set the configuration file 1800 viper.SetEnvPrefix("CORE") 1801 viper.AutomaticEnv() 1802 replacer := strings.NewReplacer(".", "_") 1803 viper.SetEnvKeyReplacer(replacer) 1804 viper.SetConfigName("chaincodetest") // name of config file (without extension) 1805 viper.AddConfigPath("./") // path to look for the config file in 1806 err := viper.ReadInConfig() // Find and read the config file 1807 if err != nil { // Handle errors reading the config file 1808 panic(fmt.Errorf("Fatal error config file: %s \n", err)) 1809 } 1810 1811 testutil.SetupTestLogging() 1812 1813 // Set the number of maxprocs 1814 var numProcsDesired = viper.GetInt("peer.gomaxprocs") 1815 chaincodeLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(numProcsDesired)) 1816 1817 // Init the BCCSP 1818 err = factory.InitFactories(nil) 1819 if err != nil { 1820 panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)) 1821 } 1822 } 1823 1824 func deployChaincode(ctx context.Context, name string, version string, chaincodeType pb.ChaincodeSpec_Type, path string, args [][]byte, creator []byte, channel string, nextBlockNumber uint64) ([]byte, *ccprovider.CCContext, error) { 1825 chaincodeSpec := &pb.ChaincodeSpec{ 1826 ChaincodeId: &pb.ChaincodeID{ 1827 Name: name, 1828 Version: version, 1829 Path: path, 1830 }, 1831 Type: chaincodeType, 1832 Input: &pb.ChaincodeInput{ 1833 Args: args, 1834 }, 1835 } 1836 1837 signedProposal, proposal := putils.MockSignedEndorserProposal2OrPanic(channel, chaincodeSpec, signer) 1838 1839 chaincodeCtx := ccprovider.NewCCContext(channel, name, version, "", false, signedProposal, proposal) 1840 1841 result, err := deploy(ctx, chaincodeCtx, chaincodeSpec, nextBlockNumber) 1842 if err != nil { 1843 return nil, chaincodeCtx, fmt.Errorf("Error deploying <%s:%s>: %s", name, version, err) 1844 } 1845 return result, chaincodeCtx, nil 1846 } 1847 1848 var signer msp.SigningIdentity 1849 1850 var rng *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano())) 1851 1852 func generateChaincodeName(chaincodeType pb.ChaincodeSpec_Type) string { 1853 prefix := "cc_" 1854 switch chaincodeType { 1855 case pb.ChaincodeSpec_GOLANG: 1856 prefix = "cc_go_" 1857 case pb.ChaincodeSpec_JAVA: 1858 prefix = "cc_java_" 1859 case pb.ChaincodeSpec_NODE: 1860 prefix = "cc_js_" 1861 } 1862 return fmt.Sprintf("%s%06d", prefix, rng.Intn(999999)) 1863 } 1864 1865 type CreatorPolicy struct { 1866 Creators [][]byte 1867 } 1868 1869 // Evaluate takes a set of SignedData and evaluates whether this set of signatures satisfies the policy 1870 func (c *CreatorPolicy) Evaluate(signatureSet []*common.SignedData) error { 1871 for _, value := range c.Creators { 1872 if bytes.Compare(signatureSet[0].Identity, value) == 0 { 1873 return nil 1874 } 1875 } 1876 return fmt.Errorf("Creator not recognized [%s]", string(signatureSet[0].Identity)) 1877 } 1878 1879 type mockPolicyCheckerFactory struct{} 1880 1881 func (f *mockPolicyCheckerFactory) NewPolicyChecker() policy.PolicyChecker { 1882 return policy.NewPolicyChecker( 1883 peer.NewChannelPolicyManagerGetter(), 1884 &mocks.MockIdentityDeserializer{[]byte("Admin"), []byte("msg1")}, 1885 &mocks.MockMSPPrincipalGetter{Principal: []byte("Admin")}, 1886 ) 1887 }