Skip to content

Commit

Permalink
FAB-10577 User supplied code-package has priority
Browse files Browse the repository at this point in the history
There is still cruft from v0.5/v0.6 in the chaincode package.  If a user
supplies a code-package with an instantiate (deploy or upgrade), this
could cause the chaincode package to erroneously ignore the package on
the local filesystem.

This CR addresses the problem by retrieving the CDS from the filesystem
first, nils out the code-package, then copies the user-init-args into
it.  The correct fix is to remove the notion of CDS from the chaincode
package, but, that is a much longer road which should be done in the
future.

Change-Id: Icd418f8974c1afc07730b727775f6783763feb9d
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Jun 8, 2018
1 parent d7656e2 commit db83887
Show file tree
Hide file tree
Showing 5 changed files with 1,280 additions and 1 deletion.
24 changes: 23 additions & 1 deletion core/endorser/endorser.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package endorser
import (
"fmt"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/crypto"
"github.com/hyperledger/fabric/common/flogging"
Expand Down Expand Up @@ -74,6 +75,9 @@ type Support interface {
// ChaincodeDefinition differs from the instantiation policy stored on the ledger
CheckInstantiationPolicy(name, version string, cd ccprovider.ChaincodeDefinition) error

// GetChaincodeDeploymentSpecFS returns the deploymentspec for a chaincode from the fs
GetChaincodeDeploymentSpecFS(cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeDeploymentSpec, error)

// GetApplicationConfig returns the configtxapplication.SharedConfig for the Channel
// and whether the Application config exists
GetApplicationConfig(cid string) (channelconfig.Application, bool)
Expand Down Expand Up @@ -150,8 +154,13 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s
// NOTE that if there's an error all simulation, including the chaincode
// table changes in lscc will be thrown away
if cid.Name == "lscc" && len(cis.ChaincodeSpec.Input.Args) >= 3 && (string(cis.ChaincodeSpec.Input.Args[0]) == "deploy" || string(cis.ChaincodeSpec.Input.Args[0]) == "upgrade") {
userCDS, err := putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.Input.Args[2])
if err != nil {
return nil, nil, err
}

var cds *pb.ChaincodeDeploymentSpec
cds, err = putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.Input.Args[2])
cds, err = e.SanitizeUserCDS(userCDS)
if err != nil {
return nil, nil, err
}
Expand All @@ -171,6 +180,19 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s
return res, ccevent, err
}

func (e *Endorser) SanitizeUserCDS(userCDS *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeDeploymentSpec, error) {
fsCDS, err := e.s.GetChaincodeDeploymentSpecFS(userCDS)
if err != nil {
return nil, errors.Wrapf(err, "cannot deploy a chaincode which is not installed")
}

sanitizedCDS := proto.Clone(fsCDS).(*pb.ChaincodeDeploymentSpec)
sanitizedCDS.CodePackage = nil
sanitizedCDS.ChaincodeSpec.Input = userCDS.ChaincodeSpec.Input

return sanitizedCDS, nil
}

// TO BE REMOVED WHEN JAVA CC IS ENABLED
// disableJavaCCInst if trying to install, instantiate or upgrade Java CC
func (e *Endorser) DisableJavaCCInst(cid *pb.ChaincodeID, cis *pb.ChaincodeInvocationSpec) error {
Expand Down
53 changes: 53 additions & 0 deletions core/endorser/endorser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"os"
"testing"

"github.com/golang/protobuf/proto"
mc "github.com/hyperledger/fabric/common/mocks/config"
"github.com/hyperledger/fabric/common/mocks/resourcesconfig"
"github.com/hyperledger/fabric/common/util"
Expand Down Expand Up @@ -667,3 +668,55 @@ func TestMain(m *testing.M) {
retVal := m.Run()
os.Exit(retVal)
}

//go:generate counterfeiter -o mocks/support.go --fake-name Support . support
type support interface {
endorser.Support
}

func TestUserCDSSanitization(t *testing.T) {
fakeSupport := &mocks.Support{}
e := endorser.NewEndorserServer(nil, fakeSupport)

userCDS := &pb.ChaincodeDeploymentSpec{
ChaincodeSpec: &pb.ChaincodeSpec{
ChaincodeId: &pb.ChaincodeID{
Name: "user-cc-name",
Version: "user-cc-version",
Path: "user-cc-path",
},
Input: &pb.ChaincodeInput{
Args: [][]byte{[]byte("foo"), []byte("bar")},
},
Type: pb.ChaincodeSpec_GOLANG,
},
CodePackage: []byte("user-code"),
}

fsCDS := &pb.ChaincodeDeploymentSpec{
ChaincodeSpec: &pb.ChaincodeSpec{
ChaincodeId: &pb.ChaincodeID{
Name: "fs-cc-name",
Version: "fs-cc-version",
Path: "fs-cc-path",
},
Type: pb.ChaincodeSpec_GOLANG,
},
CodePackage: []byte("fs-code"),
}

fakeSupport.GetChaincodeDeploymentSpecFSReturns(fsCDS, nil)

sanitizedCDS, err := e.SanitizeUserCDS(userCDS)
assert.NoError(t, err)
assert.Nil(t, sanitizedCDS.CodePackage)
assert.True(t, proto.Equal(userCDS.ChaincodeSpec.Input, sanitizedCDS.ChaincodeSpec.Input))
assert.True(t, proto.Equal(fsCDS.ChaincodeSpec.ChaincodeId, sanitizedCDS.ChaincodeSpec.ChaincodeId))

t.Run("BadPath", func(t *testing.T) {
fakeSupport.GetChaincodeDeploymentSpecFSReturns(nil, fmt.Errorf("fake-error"))
_, err := e.SanitizeUserCDS(userCDS)
assert.Error(t, err)
assert.Contains(t, err.Error(), "fake-error")
})
}
Loading

0 comments on commit db83887

Please sign in to comment.