Skip to content

Commit 3169234

Browse files
author
Srinivasan Muralidharan
committed
FAB-2081 allow user CC to call system CC
https://jira.hyperledger.org/browse/FAB-2081 Chaincode to chaincode invocation works only if the called chaincode is a user chaincode. Add the ability to call system chaincode as well and add a UT for it. Change-Id: Icbe28493e32f9e98ea7e046fdae3287b16c59cb2 Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent 3295920 commit 3169234

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

core/chaincode/exectransaction_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,71 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) {
13861386
theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2})
13871387
}
13881388

1389+
// Test the execution of a chaincode that invokes system chaincode
1390+
// uses the "pthru" chaincode to query "lccc" for the "pthru" chaincode
1391+
func TestChaincodeInvokesSystemChaincode(t *testing.T) {
1392+
chainID := util.GetTestChainID()
1393+
1394+
lis, err := initPeer(chainID)
1395+
if err != nil {
1396+
t.Fail()
1397+
t.Logf("Error creating peer: %s", err)
1398+
}
1399+
1400+
defer finitPeer(lis, chainID)
1401+
1402+
var ctxt = context.Background()
1403+
1404+
var nextBlockNumber uint64
1405+
1406+
// Deploy second chaincode
1407+
url := "github.com/hyperledger/fabric/examples/chaincode/go/passthru"
1408+
1409+
cID := &pb.ChaincodeID{Name: "pthru", Path: url, Version: "0"}
1410+
f := "init"
1411+
args := util.ToChaincodeArgs(f)
1412+
1413+
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}}
1414+
1415+
cccid := ccprovider.NewCCContext(chainID, "pthru", "0", "", false, nil, nil)
1416+
1417+
_, err = deploy(ctxt, cccid, spec, nextBlockNumber)
1418+
nextBlockNumber++
1419+
ccID := spec.ChaincodeId.Name
1420+
if err != nil {
1421+
t.Fail()
1422+
t.Logf("Error initializing chaincode %s(%s)", ccID, err)
1423+
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
1424+
return
1425+
}
1426+
1427+
time.Sleep(time.Second)
1428+
1429+
//send an invoke to pass thru to query "lccc" system chaincode on chainID to get
1430+
//information about "pthru"
1431+
args = util.ToChaincodeArgs("lccc/"+chainID, "getid", chainID, "pthru")
1432+
1433+
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: args}}
1434+
// Invoke chaincode
1435+
_, _, retval, err := invoke(ctxt, chainID, spec, nextBlockNumber)
1436+
1437+
if err != nil {
1438+
t.Fail()
1439+
t.Logf("Error invoking <%s>: %s", ccID, err)
1440+
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
1441+
return
1442+
}
1443+
1444+
if string(retval) != "pthru" {
1445+
t.Fail()
1446+
t.Logf("Expected to get back \"pthru\" from lccc but got back %s", string(retval))
1447+
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
1448+
return
1449+
}
1450+
1451+
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
1452+
}
1453+
13891454
var signer msp.SigningIdentity
13901455

13911456
func TestMain(m *testing.M) {

core/chaincode/handler.go

+20-7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
commonledger "github.com/hyperledger/fabric/common/ledger"
2828
"github.com/hyperledger/fabric/common/util"
2929
"github.com/hyperledger/fabric/core/common/ccprovider"
30+
"github.com/hyperledger/fabric/core/common/sysccprovider"
3031
ccintf "github.com/hyperledger/fabric/core/container/ccintf"
3132
"github.com/hyperledger/fabric/core/ledger"
3233
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
@@ -1314,15 +1315,27 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) {
13141315
}
13151316

13161317
//Call LCCC to get the called chaincode artifacts
1318+
1319+
//is the chaincode a system chaincode ?
1320+
isscc := sysccprovider.GetSystemChaincodeProvider().IsSysCC(calledCcParts.name)
1321+
13171322
var cd *ccprovider.ChaincodeData
1318-
cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.signedProp, txContext.proposal, calledCcParts.suffix, calledCcParts.name)
1319-
if err != nil {
1320-
payload := []byte(err.Error())
1321-
chaincodeLogger.Debugf("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s",
1322-
shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
1323-
triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
1324-
return
1323+
if !isscc {
1324+
//if its a user chaincode, get the details from LCCC
1325+
//Call LCCC to get the called chaincode artifacts
1326+
cd, err = GetChaincodeDataFromLCCC(ctxt, msg.Txid, txContext.signedProp, txContext.proposal, calledCcParts.suffix, calledCcParts.name)
1327+
if err != nil {
1328+
payload := []byte(err.Error())
1329+
chaincodeLogger.Debugf("[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s",
1330+
shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR)
1331+
triggerNextStateMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid}
1332+
return
1333+
}
1334+
} else {
1335+
//this is a system cc, just call it directly
1336+
cd = &ccprovider.ChaincodeData{Name: calledCcParts.name, Version: util.GetSysCCVersion()}
13251337
}
1338+
13261339
cccid := ccprovider.NewCCContext(calledCcParts.suffix, calledCcParts.name, cd.Version, msg.Txid, false, txContext.signedProp, txContext.proposal)
13271340

13281341
// Launch the new chaincode if not already running

0 commit comments

Comments
 (0)