Skip to content

Commit

Permalink
fab-2220 getcc record not to check for CC existence
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-2220

LCCC exposes the following "GET" api.
   * getid - gets the name given name (basically "exists")
   * getccdata - gets the record entry for the chaincode given name
   * getdepspec - gets the deployment spec for the chaincode given name

Of these only the later needs the chaincode to be available on the peer.
Other APIs should not look for the existence of the chaincode.

This is needed for TXs to be committed on peer even if the chaincode
is not available on it

Change-Id: I34e336128880ccd3d5f82733a17b6e15fb14ec50
Signed-off-by: Srinivasan Muralidharan <muralisr@us.ibm.com>
  • Loading branch information
Srinivasan Muralidharan committed Feb 14, 2017
1 parent 9f561b8 commit 7294874
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 12 deletions.
33 changes: 21 additions & 12 deletions core/scc/lccc/lccc.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (lccc *LifeCycleSysCC) putChaincodeData(stub shim.ChaincodeStubInterface, c
}

//checks for existence of chaincode on the given chain
func (lccc *LifeCycleSysCC) getChaincode(stub shim.ChaincodeStubInterface, ccname string) (*ccprovider.ChaincodeData, []byte, error) {
func (lccc *LifeCycleSysCC) getChaincode(stub shim.ChaincodeStubInterface, ccname string, checkFS bool) (*ccprovider.ChaincodeData, []byte, error) {
cdbytes, err := stub.GetState(ccname)
if err != nil {
return nil, nil, err
Expand All @@ -235,9 +235,11 @@ func (lccc *LifeCycleSysCC) getChaincode(stub shim.ChaincodeStubInterface, ccnam
return nil, nil, MarshallErr(ccname)
}

cd.DepSpec, _, err = ccprovider.GetChaincodeFromFS(ccname, cd.Version)
if err != nil {
return nil, nil, InvalidDeploymentSpecErr(err.Error())
if checkFS {
cd.DepSpec, _, err = ccprovider.GetChaincodeFromFS(ccname, cd.Version)
if err != nil {
return cd, nil, InvalidDeploymentSpecErr(err.Error())
}
}

return cd, cdbytes, nil
Expand Down Expand Up @@ -326,7 +328,7 @@ func (lccc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chai
return err
}

cd, _, err := lccc.getChaincode(stub, cds.ChaincodeSpec.ChaincodeId.Name)
cd, _, err := lccc.getChaincode(stub, cds.ChaincodeSpec.ChaincodeId.Name, true)
if cd != nil {
return ExistsErr(cds.ChaincodeSpec.ChaincodeId.Name)
}
Expand Down Expand Up @@ -381,7 +383,7 @@ func (lccc *LifeCycleSysCC) executeUpgrade(stub shim.ChaincodeStubInterface, cha
}

// check for existence of chaincode
cd, _, err := lccc.getChaincode(stub, chaincodeName)
cd, _, err := lccc.getChaincode(stub, chaincodeName, true)
if cd == nil {
return nil, NotFoundErr(chainName)
}
Expand Down Expand Up @@ -529,20 +531,27 @@ func (lccc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response

chain := string(args[1])
ccname := string(args[2])
//get chaincode given <chain, name>

cd, cdbytes, _ := lccc.getChaincode(stub, ccname)
//check the FS only for deployment spec
//other calls are looking for LCCC entries only
checkFS := false
if function == GETDEPSPEC {
checkFS = true
}
cd, cdbytes, err := lccc.getChaincode(stub, ccname, checkFS)
if cd == nil || cdbytes == nil {
logger.Debugf("ChaincodeID: %s does not exist on channel: %s ", ccname, chain)
logger.Errorf("ChaincodeId: %s does not exist on channel: %s(err:%s)", ccname, chain, err)
return shim.Error(TXNotFoundErr(ccname + "/" + chain).Error())
}

if function == GETCCINFO {
switch function {
case GETCCINFO:
return shim.Success([]byte(cd.Name))
} else if function == GETCCDATA {
case GETCCDATA:
return shim.Success(cdbytes)
default:
return shim.Success(cd.DepSpec)
}
return shim.Success(cd.DepSpec)
}

return shim.Error(InvalidFunctionErr(function).Error())
Expand Down
45 changes: 45 additions & 0 deletions core/scc/lccc/lccc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,51 @@ func TestUpgradeNonExistChaincode(t *testing.T) {
}
}

//TestGetAPIsWithoutInstall get functions should return the right responses when chaicode is on
//ledger but not on FS
func TestGetAPIsWithoutInstall(t *testing.T) {
scc := new(LifeCycleSysCC)
stub := shim.NewMockStub("lccc", scc)

if res := stub.MockInit("1", nil); res.Status != shim.OK {
fmt.Println("Init failed", string(res.Message))
t.FailNow()
}

cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true)

var b []byte
if b, err = proto.Marshal(cds); err != nil || b == nil {
t.FailNow()
}

args := [][]byte{[]byte(DEPLOY), []byte("test"), b}
if res := stub.MockInvoke("1", args); res.Status != shim.OK {
t.FailNow()
}

//Force remove CC
os.Remove(lccctestpath + "/example02.0")

//GETCCINFO should still work
args = [][]byte{[]byte(GETCCINFO), []byte("test"), []byte(cds.ChaincodeSpec.ChaincodeId.Name)}
if res := stub.MockInvoke("1", args); res.Status != shim.OK {
t.FailNow()
}

//GETCCDATA should still work
args = [][]byte{[]byte(GETCCDATA), []byte("test"), []byte(cds.ChaincodeSpec.ChaincodeId.Name)}
if res := stub.MockInvoke("1", args); res.Status != shim.OK {
t.FailNow()
}

//GETDEPSPEC should not work
args = [][]byte{[]byte(GETDEPSPEC), []byte("test"), []byte(cds.ChaincodeSpec.ChaincodeId.Name)}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.FailNow()
}
}

func TestMain(m *testing.M) {
ccprovider.SetChaincodesPath(lccctestpath)
sysccprovider.RegisterSystemChaincodeProviderFactory(&mocksccProviderFactory{})
Expand Down

0 comments on commit 7294874

Please sign in to comment.