exectransaction_test.go 61.8 KB
Newer Older
1
/*
2
Copyright IBM Corp. All Rights Reserved.
3

4
SPDX-License-Identifier: Apache-2.0
5
6
7
8
9
*/

package chaincode

import (
10
11
	"bytes"
	"encoding/json"
12
	"errors"
13
	"flag"
14
	"fmt"
15
	"math/rand"
16
17
	"net"
	"os"
18
	"path/filepath"
19
	"runtime"
20
	"strconv"
21
	"strings"
22
23
24
25
	"sync"
	"testing"
	"time"

26
	"github.com/golang/protobuf/proto"
27
	"github.com/hyperledger/fabric/bccsp/factory"
28
	mc "github.com/hyperledger/fabric/common/mocks/config"
29
30
	mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
	"github.com/hyperledger/fabric/common/policies"
Jason Yellick's avatar
Jason Yellick committed
31
	"github.com/hyperledger/fabric/common/util"
32
33
	"github.com/hyperledger/fabric/core/aclmgmt"
	aclmocks "github.com/hyperledger/fabric/core/aclmgmt/mocks"
34
	"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
35
	"github.com/hyperledger/fabric/core/common/ccprovider"
36
	"github.com/hyperledger/fabric/core/config"
37
38
	"github.com/hyperledger/fabric/core/container"
	"github.com/hyperledger/fabric/core/container/ccintf"
39
	"github.com/hyperledger/fabric/core/ledger"
40
41
	"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
42
	cut "github.com/hyperledger/fabric/core/ledger/util"
43
	"github.com/hyperledger/fabric/core/ledger/util/couchdb"
44
	cmp "github.com/hyperledger/fabric/core/mocks/peer"
45
	"github.com/hyperledger/fabric/core/peer"
46
	"github.com/hyperledger/fabric/core/policy"
47
	"github.com/hyperledger/fabric/core/policy/mocks"
48
	"github.com/hyperledger/fabric/core/scc"
49
	"github.com/hyperledger/fabric/core/testutil"
50
	"github.com/hyperledger/fabric/msp"
51
	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
52
	"github.com/hyperledger/fabric/msp/mgmt/testtools"
53
	"github.com/hyperledger/fabric/protos/common"
54
55
	pb "github.com/hyperledger/fabric/protos/peer"
	putils "github.com/hyperledger/fabric/protos/utils"
56
57
58
59
60
61
	"github.com/spf13/viper"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

62
63
64
65
66
67
68
69
70
var runTests bool

func testForSkip(t *testing.T) {
	//run tests
	if !runTests {
		t.SkipNow()
	}
}

71
//initialize peer and start up. If security==enabled, login as vp
72
func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), error) {
73
	//start clean
74
	finitPeer(nil, chainIDs...)
75

76
77
78
79
80
81
82
83
84
85
	msi := &cmp.MockSupportImpl{
		GetApplicationConfigRv:     &mc.MockApplication{CapabilitiesRv: &mc.MockApplicationCapabilities{}},
		GetApplicationConfigBoolRv: true,
	}
	sccp := &scc.ProviderImpl{Peer: peer.Default, PeerSupport: msi}

	mockAclProvider = &aclmocks.MockACLProvider{}
	mockAclProvider.Reset()
	aclmgmt.RegisterACLProvider(mockAclProvider)

86
87
	peer.MockInitialize()

88
	mspGetter := func(cid string) []string {
89
		return []string{"SampleOrg"}
90
91
92
93
	}

	peer.MockSetMSPIDGetter(mspGetter)

94
95
96
	// For unit-test, tls is not required.
	viper.Set("peer.tls.enabled", false)

97
98
	var opts []grpc.ServerOption
	if viper.GetBool("peer.tls.enabled") {
99
		creds, err := credentials.NewServerTLSFromFile(config.GetPath("peer.tls.cert.file"), config.GetPath("peer.tls.key.file"))
100
		if err != nil {
101
			return nil, nil, nil, fmt.Errorf("Failed to generate credentials %v", err)
102
103
104
105
106
		}
		opts = []grpc.ServerOption{grpc.Creds(creds)}
	}
	grpcServer := grpc.NewServer(opts...)

107
108
	peerAddress, err := peer.GetLocalAddress()
	if err != nil {
109
		return nil, nil, nil, fmt.Errorf("Error obtaining peer address: %s", err)
110
	}
111
112
	lis, err := net.Listen("tcp", peerAddress)
	if err != nil {
113
		return nil, nil, nil, fmt.Errorf("Error starting peer listener %s", err)
114
115
	}

116
	ccStartupTimeout := time.Duration(3) * time.Minute
117
	ccprovider.SetChaincodesPath(ccprovider.GetCCsPath())
118
	ca, _ := accesscontrol.NewCA()
119
	certGenerator := accesscontrol.NewAuthenticator(ca)
120
121
122
123
124
125
126
127
128
129
	chaincodeSupport := NewChaincodeSupport(
		GlobalConfig(),
		peerAddress,
		false,
		ccStartupTimeout,
		ca.CertBytes(),
		certGenerator,
		&ccprovider.CCInfoFSImpl{},
		aclmgmt.GetACLProvider(),
	)
130
	chaincodeSupport.SetSysCCProvider(sccp)
131
132
	SideEffectInitialize(chaincodeSupport)
	pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport)
133

134
135
136
	// Mock policy checker
	policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{})

137
	scc.RegisterSysCCs()
138
139

	for _, id := range chainIDs {
140
		scc.DeDeploySysCCs(id)
141
142
		if err = peer.MockCreateChain(id); err != nil {
			closeListenerAndSleep(lis)
143
			return nil, nil, nil, err
144
		}
145
		scc.DeploySysCCs(id)
146
147
148
149
		// any chain other than the default testchainid does not have a MSP set up -> create one
		if id != util.GetTestChainID() {
			mspmgmt.XXXSetMSPManager(id, mspmgmt.GetManagerForChain(util.GetTestChainID()))
		}
150
	}
151

152
153
	go grpcServer.Serve(lis)

154
155
	// was passing nil nis at top
	return lis, chaincodeSupport, func() { finitPeer(lis, chainIDs...) }, nil
156
157
}

158
func finitPeer(lis net.Listener, chainIDs ...string) {
159
	if lis != nil {
160
		for _, c := range chainIDs {
161
			scc.DeDeploySysCCs(c)
162
			if lgr := peer.GetLedger(c); lgr != nil {
163
164
				lgr.Close()
			}
165
166
167
		}
		closeListenerAndSleep(lis)
	}
168
	ledgermgmt.CleanupTestEnv()
169
	ledgerPath := config.GetPath("peer.fileSystemPath")
170
	os.RemoveAll(ledgerPath)
171
	os.RemoveAll(filepath.Join(os.TempDir(), "hyperledger"))
172
173
174
175
176
177
178
179
180

	//if couchdb is enabled, then cleanup the test couchdb
	if ledgerconfig.IsCouchDBEnabled() == true {

		chainID := util.GetTestChainID()

		connectURL := viper.GetString("ledger.state.couchDBConfig.couchDBAddress")
		username := viper.GetString("ledger.state.couchDBConfig.username")
		password := viper.GetString("ledger.state.couchDBConfig.password")
181
182
		maxRetries := viper.GetInt("ledger.state.couchDBConfig.maxRetries")
		maxRetriesOnStartup := viper.GetInt("ledger.state.couchDBConfig.maxRetriesOnStartup")
183
		requestTimeout := viper.GetDuration("ledger.state.couchDBConfig.requestTimeout")
184

185
		couchInstance, _ := couchdb.CreateCouchInstance(connectURL, username, password, maxRetries, maxRetriesOnStartup, requestTimeout)
186
		db := couchdb.CouchDatabase{CouchInstance: *couchInstance, DBName: chainID}
187
188
189
190
		//drop the test database
		db.DropDatabase()

	}
191
192
}

193
func startTxSimulation(ctxt context.Context, chainID string, txid string) (context.Context, ledger.TxSimulator, error) {
194
	lgr := peer.GetLedger(chainID)
195
	txsim, err := lgr.NewTxSimulator(txid)
196
197
198
	if err != nil {
		return nil, nil, err
	}
199
200
201
202
	historyQueryExecutor, err := lgr.NewHistoryQueryExecutor()
	if err != nil {
		return nil, nil, err
	}
203
204

	ctxt = context.WithValue(ctxt, TXSimulatorKey, txsim)
205
	ctxt = context.WithValue(ctxt, HistoryQueryExecutorKey, historyQueryExecutor)
206
207
208
	return ctxt, txsim, nil
}

209
func endTxSimulationCDS(chainID string, txid string, txsim ledger.TxSimulator, payload []byte, commit bool, cds *pb.ChaincodeDeploymentSpec, blockNumber uint64) error {
210
211
212
213
214
	// get serialized version of the signer
	ss, err := signer.Serialize()
	if err != nil {
		return err
	}
215
216
217
218
219
220
221

	// get lscc ChaincodeID
	lsccid := &pb.ChaincodeID{
		Name:    "lscc",
		Version: util.GetSysCCVersion(),
	}

222
	// get a proposal - we need it to get a transaction
223
	prop, _, err := putils.CreateDeployProposalFromCDS(chainID, cds, ss, nil, nil, nil, nil)
224
225
226
227
	if err != nil {
		return err
	}

228
	return endTxSimulation(chainID, lsccid, txsim, payload, commit, prop, blockNumber)
229
230
}

231
func endTxSimulationCIS(chainID string, ccid *pb.ChaincodeID, txid string, txsim ledger.TxSimulator, payload []byte, commit bool, cis *pb.ChaincodeInvocationSpec, blockNumber uint64) error {
232
233
234
235
236
	// get serialized version of the signer
	ss, err := signer.Serialize()
	if err != nil {
		return err
	}
237

238
	// get a proposal - we need it to get a transaction
239
	prop, returnedTxid, err := putils.CreateProposalFromCISAndTxid(txid, common.HeaderType_ENDORSER_TRANSACTION, chainID, cis, ss)
240
241
242
	if err != nil {
		return err
	}
243
244
245
	if returnedTxid != txid {
		return errors.New("txids are not same")
	}
246

247
	return endTxSimulation(chainID, ccid, txsim, payload, commit, prop, blockNumber)
248
249
}

250
251
252
253
254
255
256
257
258
259
//getting a crash from ledger.Commit when doing concurrent invokes
//It is likely intentional that ledger.Commit is serial (ie, the real
//Committer will invoke this serially on each block). Mimic that here
//by forcing serialization of the ledger.Commit call.
//
//NOTE-this should NOT have any effect on the older serial tests.
//This affects only the tests in concurrent_test.go which call these
//concurrently (100 concurrent invokes followed by 100 concurrent queries)
var _commitLock_ sync.Mutex

260
func endTxSimulation(chainID string, ccid *pb.ChaincodeID, txsim ledger.TxSimulator, _ []byte, commit bool, prop *pb.Proposal, blockNumber uint64) error {
261
	txsim.Done()
262
	if lgr := peer.GetLedger(chainID); lgr != nil {
263
		if commit {
264
265
			var txSimulationResults *ledger.TxSimulationResults
			var txSimulationBytes []byte
266
267
			var err error

268
269
			txsim.Done()

270
271
272
273
			//get simulation results
			if txSimulationResults, err = txsim.GetTxSimulationResults(); err != nil {
				return err
			}
274
275
276
			if txSimulationBytes, err = txSimulationResults.GetPubSimulationBytes(); err != nil {
				return nil
			}
277
			// assemble a (signed) proposal response message
278
279
			resp, err := putils.CreateProposalResponse(prop.Header, prop.Payload, &pb.Response{Status: 200},
				txSimulationBytes, nil, ccid, nil, signer)
280
281
282
			if err != nil {
				return err
			}
283
284
285

			// get the envelope
			env, err := putils.CreateSignedTx(prop, signer, resp)
286
287
288
			if err != nil {
				return err
			}
289
290
291
292
293
294

			envBytes, err := putils.GetBytesEnvelope(env)
			if err != nil {
				return err
			}

295
			//create the block with 1 transaction
296
			block := common.NewBlock(blockNumber, []byte{})
297
			block.Data.Data = [][]byte{envBytes}
298
299
300
			txsFilter := cut.NewTxValidationFlagsSetValue(len(block.Data.Data), pb.TxValidationCode_VALID)
			block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter

301
			//commit the block
302
303
304
305

			//see comment on _commitLock_
			_commitLock_.Lock()
			defer _commitLock_.Unlock()
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

			blockAndPvtData := &ledger.BlockAndPvtData{
				Block:        block,
				BlockPvtData: make(map[uint64]*ledger.TxPvtData),
			}

			// All tests are performed with just one transaction in a block.
			// Hence, we can simiplify the procedure of constructing the
			// block with private data. There is not enough need to
			// add more than one transaction in a block for testing chaincode
			// API.

			// ASSUMPTION: Only one transaction in a block.
			seqInBlock := uint64(0)

			if txSimulationResults.PvtSimulationResults != nil {

				blockAndPvtData.BlockPvtData[seqInBlock] = &ledger.TxPvtData{
					SeqInBlock: seqInBlock,
					WriteSet:   txSimulationResults.PvtSimulationResults,
				}
			}

			if err := lgr.CommitWithPvtData(blockAndPvtData); err != nil {
330
331
332
333
334
335
336
337
				return err
			}
		}
	}

	return nil
}

338
// Build a chaincode.
339
func getDeploymentSpec(_ context.Context, spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) {
340
341
342
343
344
	fmt.Printf("getting deployment spec for chaincode spec: %v\n", spec)
	codePackageBytes, err := container.GetChaincodePackageBytes(spec)
	if err != nil {
		return nil, err
	}
345
346
	cdDeploymentSpec := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes}
	return cdDeploymentSpec, nil
347
348
}

349
350
//getDeployLSCCSpec gets the spec for the chaincode deployment to be sent to LSCC
func getDeployLSCCSpec(chainID string, cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeInvocationSpec, error) {
351
352
353
354
355
	b, err := proto.Marshal(cds)
	if err != nil {
		return nil, err
	}

356
357
	sysCCVers := util.GetSysCCVersion()

358
359
	//wrap the deployment in an invocation spec to lscc...
	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}}}}
360

361
	return lsccSpec, nil
362
363
}

364
// Deploy a chaincode - i.e., build and initialize.
365
func deploy(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeSpec, blockNumber uint64, chaincodeSupport *ChaincodeSupport) (b []byte, err error) {
366
	// First build and get the deployment spec
367
	cdDeploymentSpec, err := getDeploymentSpec(ctx, spec)
368
369
370
371
	if err != nil {
		return nil, err
	}

372
	return deploy2(ctx, cccid, cdDeploymentSpec, blockNumber, chaincodeSupport)
373
374
}

375
func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec, blockNumber uint64, chaincodeSupport *ChaincodeSupport) (b []byte, err error) {
376
	cis, err := getDeployLSCCSpec(cccid.ChainID, chaincodeDeploymentSpec)
377
	if err != nil {
378
		return nil, fmt.Errorf("Error creating lscc spec : %s\n", err)
379
380
	}

381
382
383
	uuid := util.GenerateUUID()
	cccid.TxID = uuid
	ctx, txsim, err := startTxSimulation(ctx, cccid.ChainID, cccid.TxID)
384
	if err != nil {
385
		return nil, fmt.Errorf("Failed to get handle to simulator: %s ", err)
386
387
	}

388
389
390
391
	defer func() {
		//no error, lets try commit
		if err == nil {
			//capture returned error from commit
392
			err = endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), true, chaincodeDeploymentSpec, blockNumber)
393
394
		} else {
			//there was an error, just close simulation and return that
395
			endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), false, chaincodeDeploymentSpec, blockNumber)
396
397
		}
	}()
398

399
400
	//ignore existence errors
	ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec)
401

402
	sysCCVers := util.GetSysCCVersion()
403
	sprop, prop := putils.MockSignedEndorserProposal2OrPanic(cccid.ChainID, cis.ChaincodeSpec, signer)
404
	lsccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, sprop, prop)
405

406
	//write to lscc
407
	if _, _, err = chaincodeSupport.ExecuteWithErrorFilter(ctx, lsccid, cis); err != nil {
408
		return nil, fmt.Errorf("Error deploying chaincode (1): %s", err)
409
	}
410

411
	if b, _, err = chaincodeSupport.ExecuteWithErrorFilter(ctx, cccid, chaincodeDeploymentSpec); err != nil {
412
		return nil, fmt.Errorf("Error deploying chaincode(2): %s", err)
413
414
	}

415
	return b, nil
416
417
}

418
// Invoke a chaincode.
419
420
func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte, chaincodeSupport *ChaincodeSupport) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) {
	return invokeWithVersion(ctx, chainID, spec.GetChaincodeId().Version, spec, blockNumber, creator, chaincodeSupport)
421
422
423
}

// Invoke a chaincode with version (needed for upgrade)
424
func invokeWithVersion(ctx context.Context, chainID string, version string, spec *pb.ChaincodeSpec, blockNumber uint64, creator []byte, chaincodeSupport *ChaincodeSupport) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) {
425
	cdInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}
426
427

	// Now create the Transactions message and send to Peer.
428
	uuid = util.GenerateUUID()
429

430
	var txsim ledger.TxSimulator
431
	ctx, txsim, err = startTxSimulation(ctx, chainID, uuid)
432
433
434
435
436
437
438
439
	if err != nil {
		return nil, uuid, nil, fmt.Errorf("Failed to get handle to simulator: %s ", err)
	}

	defer func() {
		//no error, lets try commit
		if err == nil {
			//capture returned error from commit
440
			err = endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), true, cdInvocationSpec, blockNumber)
441
442
		} else {
			//there was an error, just close simulation and return that
443
			endTxSimulationCIS(chainID, spec.ChaincodeId, uuid, txsim, []byte("invoke"), false, cdInvocationSpec, blockNumber)
444
		}
445
446
	}()

447
448
449
450
	if len(creator) == 0 {
		creator = []byte("Admin")
	}
	sprop, prop := putils.MockSignedEndorserProposalOrPanic(chainID, spec, creator, []byte("msg1"))
451
	cccid := ccprovider.NewCCContext(chainID, cdInvocationSpec.ChaincodeSpec.ChaincodeId.Name, version, uuid, false, sprop, prop)
452
	retval, ccevt, err = chaincodeSupport.ExecuteWithErrorFilter(ctx, cccid, cdInvocationSpec)
453
	if err != nil {
454
		return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s", err)
455
456
	}

457
	return ccevt, uuid, retval, err
458
459
460
461
462
463
464
465
466
}

func closeListenerAndSleep(l net.Listener) {
	if l != nil {
		l.Close()
		time.Sleep(2 * time.Second)
	}
}

467
func executeDeployTransaction(t *testing.T, chainID string, name string, url string) {
468
	_, chaincodeSupport, cleanup, err := initPeer(chainID)
469
470
	if err != nil {
		t.Fail()
471
		t.Logf("Error creating peer: %s", err)
472
473
	}

474
	defer cleanup()
475
476
477
478

	var ctxt = context.Background()

	f := "init"
479
	args := util.ToChaincodeArgs(f, "a", "100", "b", "200")
480
	spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: url, Version: "0"}, Input: &pb.ChaincodeInput{Args: args}}
481

482
	cccid := ccprovider.NewCCContext(chainID, name, "0", "", false, nil, nil)
483

484
	_, err = deploy(ctxt, cccid, spec, 0, chaincodeSupport)
485

486
	cID := spec.ChaincodeId.Name
487
	if err != nil {
488
		chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
489
		t.Fail()
490
		t.Logf("Error deploying <%s>: %s", cID, err)
491
492
493
		return
	}

494
	chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
495
496
497
}

// Check the correctness of the final state after transaction execution.
498
func checkFinalState(cccid *ccprovider.CCContext, a int, b int) error {
499
500
	txid := util.GenerateUUID()
	_, txsim, err := startTxSimulation(context.Background(), cccid.ChainID, txid)
501
502
	if err != nil {
		return fmt.Errorf("Failed to get handle to simulator: %s ", err)
503
504
	}

505
506
	defer txsim.Done()

507
508
	cName := cccid.GetCanonicalName()

509
510
	// Invoke ledger to get state
	var Aval, Bval int
511
	resbytes, resErr := txsim.GetState(cccid.Name, "a")
512
	if resErr != nil {
513
		return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
514
515
516
517
	}
	fmt.Printf("Got string: %s\n", string(resbytes))
	Aval, resErr = strconv.Atoi(string(resbytes))
	if resErr != nil {
518
		return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
519
	}
520
521
	if Aval != a {
		return fmt.Errorf("Incorrect result. Aval %d != %d <%s>", Aval, a, cName)
522
523
	}

524
	resbytes, resErr = txsim.GetState(cccid.Name, "b")
525
	if resErr != nil {
526
		return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
527
528
529
	}
	Bval, resErr = strconv.Atoi(string(resbytes))
	if resErr != nil {
530
		return fmt.Errorf("Error retrieving state from ledger for <%s>: %s", cName, resErr)
531
	}
532
533
	if Bval != b {
		return fmt.Errorf("Incorrect result. Bval %d != %d <%s>", Bval, b, cName)
534
535
536
537
538
539
540
541
	}

	// Success
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
	return nil
}

// Invoke chaincode_example02
542
func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContext, cID *pb.ChaincodeID, chaincodeType pb.ChaincodeSpec_Type, args []string, destroyImage bool, chaincodeSupport *ChaincodeSupport) error {
543
544
	// the ledger is created with genesis block. Start block number 1 onwards
	var nextBlockNumber uint64 = 1
545
	f := "init"
546
	argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200")
547
	spec := &pb.ChaincodeSpec{Type: chaincodeType, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: argsDeploy}}
548
	_, err := deploy(ctxt, cccid, spec, nextBlockNumber, chaincodeSupport)
549
	nextBlockNumber++
550
	ccID := spec.ChaincodeId.Name
551
	if err != nil {
552
		return fmt.Errorf("Error deploying <%s>: %s", ccID, err)
553
554
555
556
557
	}

	time.Sleep(time.Second)

	if destroyImage {
558
559
		chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
		dir := container.DestroyImageReq{CCID: ccintf.CCID{ChaincodeSpec: spec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID}, Force: true, NoPrune: true}
560
561
562
563
564
565
566
567
568

		_, err = container.VMCProcess(ctxt, container.DOCKER, dir)
		if err != nil {
			err = fmt.Errorf("Error destroying image: %s", err)
			return err
		}
	}

	f = "invoke"
569
	invokeArgs := append([]string{f}, args...)
570
	spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(invokeArgs...)}}
571
	_, uuid, _, err := invoke(ctxt, cccid.ChainID, spec, nextBlockNumber, nil, chaincodeSupport)
572
	nextBlockNumber++
573
	if err != nil {
574
		return fmt.Errorf("Error invoking <%s>: %s", cccid.Name, err)
575
576
	}

577
	cccid.TxID = uuid
578
	err = checkFinalState(cccid, 90, 210)
579
	if err != nil {
580
		return fmt.Errorf("Incorrect final state after transaction for <%s>: %s", ccID, err)
581
582
583
584
	}

	// Test for delete state
	f = "delete"
585
	delArgs := util.ToChaincodeArgs(f, "a")
586
	spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: delArgs}}
587
	_, _, _, err = invoke(ctxt, cccid.ChainID, spec, nextBlockNumber, nil, chaincodeSupport)
588
	if err != nil {
589
		return fmt.Errorf("Error deleting state in <%s>: %s", cccid.Name, err)
590
591
592
593
594
	}

	return nil
}

595
const (
596
	chaincodeExample02GolangPath   = "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
597
	chaincodeExample04GolangPath   = "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example04"
598
599
	chaincodeEventSenderGolangPath = "github.com/hyperledger/fabric/examples/chaincode/go/eventsender"
	chaincodeExample02JavaPath     = "../../examples/chaincode/java/chaincode_example02"
600
	chaincodeExample04JavaPath     = "../../examples/chaincode/java/chaincode_example04"
601
602
	chaincodeExample06JavaPath     = "../../examples/chaincode/java/chaincode_example06"
	chaincodeEventSenderJavaPath   = "../../examples/chaincode/java/eventsender"
603
604
)

605
func runChaincodeInvokeChaincode(t *testing.T, channel1 string, channel2 string, tc tcicTc, cccid1 *ccprovider.CCContext, expectedA int, expectedB int, nextBlockNumber1, nextBlockNumber2 uint64, chaincodeSupport *ChaincodeSupport) (uint64, uint64) {
606
607
	var ctxt = context.Background()

608
609
610
611
612
613
614
	// chaincode2: the chaincode that will call by chaincode1
	chaincode2Name := generateChaincodeName(tc.chaincodeType)
	chaincode2Version := "0"
	chaincode2Type := tc.chaincodeType
	chaincode2Path := tc.chaincodePath
	chaincode2InitArgs := util.ToChaincodeArgs("init", "e", "0")
	chaincode2Creator := []byte([]byte("Alice"))
615

616
	// deploy second chaincode on channel1
617
	_, cccid2, err := deployChaincode(ctxt, chaincode2Name, chaincode2Version, chaincode2Type, chaincode2Path, chaincode2InitArgs, chaincode2Creator, channel1, nextBlockNumber1, chaincodeSupport)
618
	if err != nil {
619
620
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
621
622
		t.Fatalf("Error initializing chaincode %s(%s)", chaincode2Name, err)
		return nextBlockNumber1, nextBlockNumber2
623
	}
624
	nextBlockNumber1++
625
626
627
628
629

	time.Sleep(time.Second)

	// Invoke second chaincode passing the first chaincode's name as first param,
	// which will inturn invoke the first chaincode
630
631
632
633
634
635
636
637
638
639
	chaincode2InvokeSpec := &pb.ChaincodeSpec{
		Type: chaincode2Type,
		ChaincodeId: &pb.ChaincodeID{
			Name:    chaincode2Name,
			Version: chaincode2Version,
		},
		Input: &pb.ChaincodeInput{
			Args: util.ToChaincodeArgs("invoke", cccid1.Name, "e", "1"),
		},
	}
640
	// Invoke chaincode
641
	_, txID, _, err := invoke(ctxt, channel1, chaincode2InvokeSpec, nextBlockNumber1, []byte("Alice"), chaincodeSupport)
642
	if err != nil {
643
644
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
645
646
		t.Fatalf("Error invoking <%s>: %s", chaincode2Name, err)
		return nextBlockNumber1, nextBlockNumber2
647
	}
648
	nextBlockNumber1++
649

650
651
	// TODO this doesn't seeem to be used, remove?
	cccid1.TxID = txID
652
653

	// Check the state in the ledger
654
	err = checkFinalState(cccid1, expectedA, expectedB)
655
	if err != nil {
656
657
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
658
659
		t.Fatalf("Incorrect final state after transaction for <%s>: %s", cccid1.Name, err)
		return nextBlockNumber1, nextBlockNumber2
660
661
	}

662
663
664
665
	// Change the policies of the two channels in such a way:
	// 1. Alice has reader access to both the channels.
	// 2. Bob has access only to chainID2.
	// Therefore the chaincode invocation should fail.
666
	pm := peer.GetPolicyManager(channel1)
667
668
669
670
	pm.(*mockpolicies.Manager).PolicyMap = map[string]policies.Policy{
		policies.ChannelApplicationWriters: &CreatorPolicy{Creators: [][]byte{[]byte("Alice")}},
	}

671
	pm = peer.GetPolicyManager(channel2)
672
673
674
675
	pm.(*mockpolicies.Manager).PolicyMap = map[string]policies.Policy{
		policies.ChannelApplicationWriters: &CreatorPolicy{Creators: [][]byte{[]byte("Alice"), []byte("Bob")}},
	}

676
	// deploy chaincode2 on channel2
677
	_, cccid3, err := deployChaincode(ctxt, chaincode2Name, chaincode2Version, chaincode2Type, chaincode2Path, chaincode2InitArgs, chaincode2Creator, channel2, nextBlockNumber2, chaincodeSupport)
678
	if err != nil {
679
680
681
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
		stopChaincode(ctxt, cccid3, chaincodeSupport)
682
683
		t.Fatalf("Error initializing chaincode %s/%s: %s", chaincode2Name, channel2, err)
		return nextBlockNumber1, nextBlockNumber2
684
	}
685
	nextBlockNumber2++
686
687
	time.Sleep(time.Second)

688
689
690
691
692
693
694
695
696
697
698
	// as Bob, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel1
	chaincode2InvokeSpec = &pb.ChaincodeSpec{
		Type: chaincode2Type,
		ChaincodeId: &pb.ChaincodeID{
			Name:    chaincode2Name,
			Version: chaincode2Version,
		},
		Input: &pb.ChaincodeInput{
			Args: util.ToChaincodeArgs("invoke", cccid1.Name, "e", "1", channel1),
		},
	}
699
	_, _, _, err = invoke(ctxt, channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Bob"), chaincodeSupport)
700
	if err == nil {
701
		// Bob should not be able to call
702
703
704
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
		stopChaincode(ctxt, cccid3, chaincodeSupport)
705
706
707
		nextBlockNumber2++
		t.Fatalf("As Bob, invoking <%s/%s> via <%s/%s> should fail, but it succeeded.", cccid1.Name, cccid1.ChainID, chaincode2Name, channel2)
		return nextBlockNumber1, nextBlockNumber2
708
709
	}

710
	// as Alice, invoke chaincode2 on channel2 so that it invokes chaincode1 on channel1
711
	_, _, _, err = invoke(ctxt, channel2, chaincode2InvokeSpec, nextBlockNumber2, []byte("Alice"), chaincodeSupport)
712
	if err != nil {
713
		// Alice should be able to call
714
715
716
		stopChaincode(ctxt, cccid1, chaincodeSupport)
		stopChaincode(ctxt, cccid2, chaincodeSupport)
		stopChaincode(ctxt, cccid3, chaincodeSupport)
717
718
		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)
		return nextBlockNumber1, nextBlockNumber2
719
	}
720
	nextBlockNumber2++
721

722
723
724
	stopChaincode(ctxt, cccid1, chaincodeSupport)
	stopChaincode(ctxt, cccid2, chaincodeSupport)
	stopChaincode(ctxt, cccid3, chaincodeSupport)
725

726
	return nextBlockNumber1, nextBlockNumber2
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
}

// Test deploy of a transaction
func TestExecuteDeployTransaction(t *testing.T) {
	//chaincoe is deployed as part of many tests. No need for a separate one for this
	t.Skip()
	chainID := util.GetTestChainID()

	executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

// Test deploy of a transaction with a GOPATH with multiple elements
func TestGopathExecuteDeployTransaction(t *testing.T) {
	//this is no longer critical as chaincode is assembled in the client side (SDK)
	t.Skip()
	chainID := util.GetTestChainID()

	// add a trailing slash to GOPATH
	// and a couple of elements - it doesn't matter what they are
	os.Setenv("GOPATH", os.Getenv("GOPATH")+string(os.PathSeparator)+string(os.PathListSeparator)+"/tmp/foo"+string(os.PathListSeparator)+"/tmp/bar")
	executeDeployTransaction(t, chainID, "example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
}

750
func TestExecuteInvokeTransaction(t *testing.T) {
751
	testForSkip(t)
752

753
754
755
756
757
758
	testCases := []struct {
		chaincodeType pb.ChaincodeSpec_Type
		chaincodePath string
	}{
		{pb.ChaincodeSpec_GOLANG, chaincodeExample02GolangPath},
		{pb.ChaincodeSpec_JAVA, chaincodeExample02JavaPath},
759
760
	}

761
762
	for _, tc := range testCases {
		t.Run(tc.chaincodeType.String(), func(t *testing.T) {
763

764
765
766
767
			if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" {
				t.Skip("No Java chaincode support yet on non-x86_64.")
			}

768
			chainID := util.GetTestChainID()
769

770
			_, chaincodeSupport, cleanup, err := initPeer(chainID)
771
772
773
774
			if err != nil {
				t.Fail()
				t.Logf("Error creating peer: %s", err)
			}
775

776
777
778
779
780
781
782
			var ctxt = context.Background()
			chaincodeName := generateChaincodeName(tc.chaincodeType)
			chaincodeVersion := "1.0.0.0"
			cccid := ccprovider.NewCCContext(chainID, chaincodeName, chaincodeVersion, "", false, nil, nil)
			ccID := &pb.ChaincodeID{Name: chaincodeName, Path: tc.chaincodePath, Version: chaincodeVersion}

			args := []string{"a", "b", "10"}
783
			err = invokeExample02Transaction(ctxt, cccid, ccID, tc.chaincodeType, args, true, chaincodeSupport)
784
785
786
787
788
789
790
791
			if err != nil {
				t.Fail()
				t.Logf("Error invoking transaction: %s", err)
			} else {
				fmt.Print("Invoke test passed\n")
				t.Log("Invoke test passed")
			}

792
793
			chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}})
			cleanup()
794
		})
795
796
797
798
799
800
	}

}

// Test the execution of an invalid transaction.
func TestExecuteInvokeInvalidTransaction(t *testing.T) {
801
802
	testForSkip(t)

803
804
	chainID := util.GetTestChainID()

805
	_, chaincodeSupport, cleanup, err := initPeer(chainID)
806
807
	if err != nil {
		t.Fail()
808
		t.Logf("Error creating peer: %s", err)
809
810
	}

811
	defer cleanup()
812
813
814
815

	var ctxt = context.Background()

	url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
816
	ccID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"}
817

818
	cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)
819

820
821
	//FAIL, FAIL!
	args := []string{"x", "-1"}
822
	err = invokeExample02Transaction(ctxt, cccid, ccID, pb.ChaincodeSpec_GOLANG, args, false, chaincodeSupport)
823
824
825
826
827

	//this HAS to fail with expectedDeltaStringPrefix
	if err != nil {
		errStr := err.Error()
		t.Logf("Got error %s\n", errStr)
828
		t.Log("InvalidInvoke test passed")
829
		chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}})
830
831
832
833
834
835
836

		return
	}

	t.Fail()
	t.Logf("Error invoking transaction %s", err)

837
	chaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}})
838
839
}

840
841
842
843
844
845
// testcase parameters for TestChaincodeInvokeChaincode
type tcicTc struct {
	chaincodeType pb.ChaincodeSpec_Type
	chaincodePath string
}

846
847
// Test the execution of a chaincode that invokes another chaincode.
func TestChaincodeInvokeChaincode(t *testing.T) {
848
	testForSkip(t)
849
850
	channel := util.GetTestChainID()
	channel2 := channel + "2"
851
	lis, chaincodeSupport, cleanup, err := initPeer(channel, channel2)
852
853
	if err != nil {
		t.Fail()
854
		t.Logf("Error creating peer: %s", err)
855
856
	}

857
	defer cleanup()
858
859
860
861
862
863
864
865
866
867

	testCases := []tcicTc{
		{pb.ChaincodeSpec_GOLANG, chaincodeExample04GolangPath},
		{pb.ChaincodeSpec_JAVA, chaincodeExample04JavaPath},
	}

	ctx := context.Background()

	var nextBlockNumber1 uint64 = 1
	var nextBlockNumber2 uint64 = 1
868

869
870
871
872
873
874
875
876
877
878
879
	// deploy the chaincode that will be called by the second chaincode
	chaincode1Name := generateChaincodeName(pb.ChaincodeSpec_GOLANG)
	chaincode1Version := "0"
	chaincode1Type := pb.ChaincodeSpec_GOLANG
	chaincode1Path := chaincodeExample02GolangPath
	initialA := 100
	initialB := 200
	chaincode1InitArgs := util.ToChaincodeArgs("init", "a", strconv.Itoa(initialA), "b", strconv.Itoa(initialB))
	chaincode1Creator := []byte([]byte("Alice"))

	// Deploy first chaincode
880
	_, chaincodeCtx, err := deployChaincode(ctx, chaincode1Name, chaincode1Version, chaincode1Type, chaincode1Path, chaincode1InitArgs, chaincode1Creator, channel, nextBlockNumber1, chaincodeSupport)
881
	if err != nil {
882
		stopChaincode(ctx, chaincodeCtx, chaincodeSupport)
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
		t.Fatalf("Error initializing chaincode %s: %s", chaincodeCtx.Name, err)
	}
	nextBlockNumber1++
	time.Sleep(time.Second)

	expectedA := initialA
	expectedB := initialB

	for _, tc := range testCases {
		t.Run(tc.chaincodeType.String(), func(t *testing.T) {

			if tc.chaincodeType == pb.ChaincodeSpec_JAVA && runtime.GOARCH != "amd64" {
				t.Skip("No Java chaincode support yet on non-x86_64.")
			}

			expectedA = expectedA - 10
			expectedB = expectedB + 10
900
			nextBlockNumber1, nextBlockNumber2 = runChaincodeInvokeChaincode(t, channel, channel2, tc, chaincodeCtx, expectedA, expectedB, nextBlockNumber1, nextBlockNumber2, chaincodeSupport)
901
		})
902
903
904
905
906
	}

	closeListenerAndSleep(lis)
}