From 9112ebfb436d7b76bbcc09c5f3bf21f9ba5fa206 Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Fri, 18 May 2018 12:46:06 -0400 Subject: [PATCH] FAB-10825 Make platform latent dependency explicit Many of the assorted 'utils' functions actually reach into the core/chaincode/platforms package to determine whether packages are valid. This historically has all been done in a source-coupled way, pulling peer details into places it does not belong. Although these 'util' functions should be refactored and removed, for the time being, we can at least make the dependency on the platforms package explicit, but requiring that an instance be passed into these util functions. This has quite the ripple throughout the code, but the CR itself should be trivial to review. Change-Id: I0cc36e2f307474ddba7f6d20028a46f3aa94faf5 Signed-off-by: Jason Yellick --- core/chaincode/chaincode_support.go | 11 ++-- core/chaincode/chaincode_support_test.go | 6 ++- core/chaincode/container_runtime.go | 15 +++--- core/chaincode/exectransaction_test.go | 8 ++- core/chaincode/platforms/car/platform.go | 5 ++ .../chaincode/platforms/car/vm_helper_test.go | 5 +- core/chaincode/platforms/golang/platform.go | 5 ++ core/chaincode/platforms/java/platform.go | 5 ++ core/chaincode/platforms/mock/platform.go | 51 ++++++++++++++++++ core/chaincode/platforms/node/platform.go | 5 ++ core/chaincode/platforms/platforms.go | 22 ++++---- core/chaincode/platforms/platforms_test.go | 28 ++++++---- core/chaincode/systemchaincode_test.go | 3 ++ core/committer/txvalidator/validator.go | 4 +- .../cc_statedb_artifacts_provider.go | 8 +-- core/container/controller.go | 9 ++-- core/container/controller_test.go | 8 +-- .../dockercontroller/dockercontroller_test.go | 5 +- core/endorser/endorser.go | 7 ++- core/endorser/endorser_test.go | 54 ++++++++++--------- .../validation/builtin/validation_logic.go | 17 +++++- .../builtin/validation_logic_test.go | 30 ++++++----- core/ledger/cceventmgmt/defs.go | 4 +- core/ledger/cceventmgmt/mgr.go | 5 +- core/ledger/kvledger/example/main/example.go | 4 +- .../marble_example/main/marble_example.go | 4 +- core/ledger/ledgermgmt/ledger_mgmt.go | 9 ++-- core/ledger/ledgermgmt/ledger_mgmt_test.go | 4 +- .../ledgermgmt/ledger_mgmt_test_exports.go | 6 ++- core/peer/peer.go | 5 +- core/peer/peer_impl.go | 9 ++-- core/peer/peer_test.go | 5 +- core/scc/cscc/configure_test.go | 3 ++ core/scc/importsysccs.go | 5 +- core/scc/lscc/lscc.go | 18 ++++--- core/scc/lscc/lscc_test.go | 52 +++++++++--------- core/scc/register.go | 5 +- core/scc/register_pluginsenabled.go | 5 +- core/scc/scc_test.go | 4 +- peer/chaincode/chaincode.go | 16 ++++++ peer/chaincode/common.go | 5 +- peer/chaincode/install.go | 2 +- peer/node/start.go | 25 ++++++--- protos/utils/proputils.go | 4 +- protos/utils/proputils_test.go | 10 ++-- 45 files changed, 354 insertions(+), 166 deletions(-) diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index aec99fa94b3..39959766b6a 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -12,6 +12,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/sysccprovider" "github.com/hyperledger/fabric/core/container/ccintf" @@ -55,6 +56,7 @@ func NewChaincodeSupport( aclProvider ACLProvider, processor Processor, sccp sysccprovider.SystemChaincodeProvider, + platformRegistry *platforms.Registry, ) *ChaincodeSupport { cs := &ChaincodeSupport{ UserRunsCC: userRunsCC, @@ -71,10 +73,11 @@ func NewChaincodeSupport( } cs.Runtime = &ContainerRuntime{ - CertGenerator: certGenerator, - Processor: processor, - CACert: caCert, - PeerAddress: peerAddress, + CertGenerator: certGenerator, + Processor: processor, + CACert: caCert, + PeerAddress: peerAddress, + PlatformRegistry: platformRegistry, CommonEnv: []string{ "CORE_CHAINCODE_LOGGING_LEVEL=" + config.LogLevel, "CORE_CHAINCODE_LOGGING_SHIM=" + config.ShimLogLevel, diff --git a/core/chaincode/chaincode_support_test.go b/core/chaincode/chaincode_support_test.go index 039e9b18ec5..53512902566 100644 --- a/core/chaincode/chaincode_support_test.go +++ b/core/chaincode/chaincode_support_test.go @@ -31,6 +31,8 @@ import ( "github.com/hyperledger/fabric/core/aclmgmt/resources" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" "github.com/hyperledger/fabric/core/chaincode/mock" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/config" @@ -170,6 +172,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) { config := GlobalConfig() config.StartupTimeout = 10 * time.Second config.ExecuteTimeout = 1 * time.Second + pr := platforms.NewRegistry(&golang.Platform{}) chaincodeSupport := NewChaincodeSupport( config, "0.0.0.0:7052", @@ -185,13 +188,14 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) { }, ), sccp, + pr, ) // Mock policy checker policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{}) ccp := &CCProviderImpl{cs: chaincodeSupport} - for _, cc := range scc.CreateSysCCs(ccp, sccp, mockAclProvider) { + for _, cc := range scc.CreateSysCCs(ccp, sccp, mockAclProvider, pr) { sccp.RegisterSysCC(cc) } diff --git a/core/chaincode/container_runtime.go b/core/chaincode/container_runtime.go index 904b09513eb..ea0b17e7cfb 100644 --- a/core/chaincode/container_runtime.go +++ b/core/chaincode/container_runtime.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/container" "github.com/hyperledger/fabric/core/container/ccintf" @@ -37,11 +38,12 @@ type CertGenerator interface { // ContainerRuntime is responsible for managing containerized chaincode. type ContainerRuntime struct { - CertGenerator CertGenerator - Processor Processor - CACert []byte - CommonEnv []string - PeerAddress string + CertGenerator CertGenerator + Processor Processor + CACert []byte + CommonEnv []string + PeerAddress string + PlatformRegistry *platforms.Registry } // Start launches chaincode in a runtime environment. @@ -59,7 +61,8 @@ func (c *ContainerRuntime) Start(ctxt context.Context, cccid *ccprovider.CCConte scr := container.StartContainerReq{ Builder: &container.PlatformBuilder{ - DeploymentSpec: cds, + DeploymentSpec: cds, + PlatformRegistry: c.PlatformRegistry, }, Args: lc.Args, Env: lc.Envs, diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 3701986b456..cd1c8405fba 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -34,6 +34,8 @@ import ( "github.com/hyperledger/fabric/core/aclmgmt" aclmocks "github.com/hyperledger/fabric/core/aclmgmt/mocks" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/config" @@ -125,6 +127,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro certGenerator := accesscontrol.NewAuthenticator(ca) config := GlobalConfig() config.StartupTimeout = 3 * time.Minute + pr := platforms.NewRegistry(&golang.Platform{}) chaincodeSupport := NewChaincodeSupport( config, peerAddress, @@ -140,6 +143,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro }, ), sccp, + pr, ) pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport) @@ -147,7 +151,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{}) ccp := &CCProviderImpl{cs: chaincodeSupport} - for _, cc := range scc.CreateSysCCs(ccp, sccp, mockAclProvider) { + for _, cc := range scc.CreateSysCCs(ccp, sccp, mockAclProvider, pr) { sccp.RegisterSysCC(cc) } @@ -352,7 +356,7 @@ func endTxSimulation(chainID string, ccid *pb.ChaincodeID, txsim ledger.TxSimula // Build a chaincode. func getDeploymentSpec(_ context.Context, spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) { fmt.Printf("getting deployment spec for chaincode spec: %v\n", spec) - codePackageBytes, err := container.GetChaincodePackageBytes(spec) + codePackageBytes, err := container.GetChaincodePackageBytes(platforms.NewRegistry(&golang.Platform{}), spec) if err != nil { return nil, err } diff --git a/core/chaincode/platforms/car/platform.go b/core/chaincode/platforms/car/platform.go index e319e69551f..fd5489388a2 100644 --- a/core/chaincode/platforms/car/platform.go +++ b/core/chaincode/platforms/car/platform.go @@ -35,6 +35,11 @@ import ( type Platform struct { } +// Name returns the name of this platform +func (carPlatform *Platform) Name() string { + return pb.ChaincodeSpec_CAR.String() +} + // ValidateSpec validates the chaincode specification for CAR types to satisfy // the platform interface. This chaincode type currently doesn't // require anything specific so we just implicitly approve any spec diff --git a/core/chaincode/platforms/car/vm_helper_test.go b/core/chaincode/platforms/car/vm_helper_test.go index baf2cb6c6f5..21be4f40010 100644 --- a/core/chaincode/platforms/car/vm_helper_test.go +++ b/core/chaincode/platforms/car/vm_helper_test.go @@ -12,6 +12,7 @@ import ( "github.com/fsouza/go-dockerclient" "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/car" "github.com/hyperledger/fabric/core/container" cutil "github.com/hyperledger/fabric/core/container/util" pb "github.com/hyperledger/fabric/protos/peer" @@ -34,13 +35,13 @@ func NewVM() (*VM, error) { // BuildChaincodeContainer builds the container for the supplied chaincode specification func (vm *VM) BuildChaincodeContainer(spec *pb.ChaincodeSpec) error { - codePackage, err := container.GetChaincodePackageBytes(spec) + codePackage, err := container.GetChaincodePackageBytes(platforms.NewRegistry(&car.Platform{}), spec) if err != nil { return fmt.Errorf("Error getting chaincode package bytes: %s", err) } cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackage} - dockerSpec, err := platforms.NewRegistry().GenerateDockerBuild(cds) + dockerSpec, err := platforms.NewRegistry(&car.Platform{}).GenerateDockerBuild(cds) if err != nil { return fmt.Errorf("Error getting chaincode docker image: %s", err) } diff --git a/core/chaincode/platforms/golang/platform.go b/core/chaincode/platforms/golang/platform.go index 9333d3890f9..7758bb17b94 100644 --- a/core/chaincode/platforms/golang/platform.go +++ b/core/chaincode/platforms/golang/platform.go @@ -98,6 +98,11 @@ func filter(vs []string, f func(string) bool) []string { return vsf } +// Name returns the name of this platform +func (goPlatform *Platform) Name() string { + return pb.ChaincodeSpec_GOLANG.String() +} + // ValidateSpec validates Go chaincodes func (goPlatform *Platform) ValidateSpec(spec *pb.ChaincodeSpec) error { path, err := url.Parse(spec.ChaincodeId.Path) diff --git a/core/chaincode/platforms/java/platform.go b/core/chaincode/platforms/java/platform.go index c10b4c80df8..590703cb4f5 100644 --- a/core/chaincode/platforms/java/platform.go +++ b/core/chaincode/platforms/java/platform.go @@ -23,6 +23,11 @@ import ( type Platform struct { } +// Name returns the name of this platform +func (javaPlatform *Platform) Name() string { + return pb.ChaincodeSpec_JAVA.String() +} + //ValidateSpec validates the java chaincode specs func (javaPlatform *Platform) ValidateSpec(spec *pb.ChaincodeSpec) error { path, err := url.Parse(spec.ChaincodeId.Path) diff --git a/core/chaincode/platforms/mock/platform.go b/core/chaincode/platforms/mock/platform.go index 0cc805449b8..6136dd52609 100644 --- a/core/chaincode/platforms/mock/platform.go +++ b/core/chaincode/platforms/mock/platform.go @@ -10,6 +10,15 @@ import ( ) type Platform struct { + NameStub func() string + nameMutex sync.RWMutex + nameArgsForCall []struct{} + nameReturns struct { + result1 string + } + nameReturnsOnCall map[int]struct { + result1 string + } ValidateSpecStub func(spec *pb.ChaincodeSpec) error validateSpecMutex sync.RWMutex validateSpecArgsForCall []struct { @@ -85,6 +94,46 @@ type Platform struct { invocationsMutex sync.RWMutex } +func (fake *Platform) Name() string { + fake.nameMutex.Lock() + ret, specificReturn := fake.nameReturnsOnCall[len(fake.nameArgsForCall)] + fake.nameArgsForCall = append(fake.nameArgsForCall, struct{}{}) + fake.recordInvocation("Name", []interface{}{}) + fake.nameMutex.Unlock() + if fake.NameStub != nil { + return fake.NameStub() + } + if specificReturn { + return ret.result1 + } + return fake.nameReturns.result1 +} + +func (fake *Platform) NameCallCount() int { + fake.nameMutex.RLock() + defer fake.nameMutex.RUnlock() + return len(fake.nameArgsForCall) +} + +func (fake *Platform) NameReturns(result1 string) { + fake.NameStub = nil + fake.nameReturns = struct { + result1 string + }{result1} +} + +func (fake *Platform) NameReturnsOnCall(i int, result1 string) { + fake.NameStub = nil + if fake.nameReturnsOnCall == nil { + fake.nameReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.nameReturnsOnCall[i] = struct { + result1 string + }{result1} +} + func (fake *Platform) ValidateSpec(spec *pb.ChaincodeSpec) error { fake.validateSpecMutex.Lock() ret, specificReturn := fake.validateSpecReturnsOnCall[len(fake.validateSpecArgsForCall)] @@ -383,6 +432,8 @@ func (fake *Platform) GetMetadataProviderReturnsOnCall(i int, result1 ccmetadata func (fake *Platform) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.nameMutex.RLock() + defer fake.nameMutex.RUnlock() fake.validateSpecMutex.RLock() defer fake.validateSpecMutex.RUnlock() fake.validateDeploymentSpecMutex.RLock() diff --git a/core/chaincode/platforms/node/platform.go b/core/chaincode/platforms/node/platform.go index b16f453a1ae..9692342a031 100644 --- a/core/chaincode/platforms/node/platform.go +++ b/core/chaincode/platforms/node/platform.go @@ -43,6 +43,11 @@ func pathExists(path string) (bool, error) { return true, err } +// Name returns the name of this platform +func (nodePlatform *Platform) Name() string { + return pb.ChaincodeSpec_NODE.String() +} + // ValidateSpec validates Go chaincodes func (nodePlatform *Platform) ValidateSpec(spec *pb.ChaincodeSpec) error { path, err := url.Parse(spec.ChaincodeId.Path) diff --git a/core/chaincode/platforms/platforms.go b/core/chaincode/platforms/platforms.go index 42344318f03..9bcfc8e70b8 100644 --- a/core/chaincode/platforms/platforms.go +++ b/core/chaincode/platforms/platforms.go @@ -16,11 +16,7 @@ import ( "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/common/metadata" - "github.com/hyperledger/fabric/core/chaincode/platforms/car" "github.com/hyperledger/fabric/core/chaincode/platforms/ccmetadata" - "github.com/hyperledger/fabric/core/chaincode/platforms/golang" - "github.com/hyperledger/fabric/core/chaincode/platforms/java" - "github.com/hyperledger/fabric/core/chaincode/platforms/node" cutil "github.com/hyperledger/fabric/core/container/util" pb "github.com/hyperledger/fabric/protos/peer" ) @@ -28,6 +24,7 @@ import ( // Interface for validating the specification and and writing the package for // the given platform type Platform interface { + Name() string ValidateSpec(spec *pb.ChaincodeSpec) error ValidateDeploymentSpec(spec *pb.ChaincodeDeploymentSpec) error GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error) @@ -53,15 +50,16 @@ type Registry struct { var logger = flogging.MustGetLogger("chaincode-platform") -// TODO, ultimately this should take the platforms as parameters -func NewRegistry() *Registry { +func NewRegistry(platformTypes ...Platform) *Registry { + platforms := make(map[string]Platform) + for _, platform := range platformTypes { + if _, ok := platforms[platform.Name()]; ok { + logger.Panicf("Multiple platforms of the same name specified: %s", platform.Name()) + } + platforms[platform.Name()] = platform + } return &Registry{ - Platforms: map[string]Platform{ - pb.ChaincodeSpec_GOLANG.String(): &golang.Platform{}, - pb.ChaincodeSpec_CAR.String(): &car.Platform{}, - pb.ChaincodeSpec_JAVA.String(): &java.Platform{}, - pb.ChaincodeSpec_NODE.String(): &node.Platform{}, - }, + Platforms: platforms, PackageWriter: PackageWriterWrapper(cutil.WriteBytesToPackage), } } diff --git a/core/chaincode/platforms/platforms_test.go b/core/chaincode/platforms/platforms_test.go index add8238c054..113865c8883 100644 --- a/core/chaincode/platforms/platforms_test.go +++ b/core/chaincode/platforms/platforms_test.go @@ -16,11 +16,7 @@ import ( "github.com/hyperledger/fabric/common/metadata" "github.com/hyperledger/fabric/core/chaincode/platforms" - "github.com/hyperledger/fabric/core/chaincode/platforms/car" - "github.com/hyperledger/fabric/core/chaincode/platforms/golang" - "github.com/hyperledger/fabric/core/chaincode/platforms/java" "github.com/hyperledger/fabric/core/chaincode/platforms/mock" - "github.com/hyperledger/fabric/core/chaincode/platforms/node" pb "github.com/hyperledger/fabric/protos/peer" . "github.com/onsi/ginkgo" @@ -297,14 +293,28 @@ ENV CORE_CHAINCODE_BUILDLEVEL=%s`, metadata.Version, metadata.BaseVersion, metad Describe("NewRegistry", func() { It("initializes with the known platform types and util writer", func() { - registry = platforms.NewRegistry() + fakePlatformFoo := &mock.Platform{} + fakePlatformFoo.NameReturns("foo") + fakePlatformBar := &mock.Platform{} + fakePlatformBar.NameReturns("bar") + + registry = platforms.NewRegistry(fakePlatformFoo, fakePlatformBar) + Expect(registry.Platforms).To(Equal(map[string]platforms.Platform{ - pb.ChaincodeSpec_GOLANG.String(): &golang.Platform{}, - pb.ChaincodeSpec_CAR.String(): &car.Platform{}, - pb.ChaincodeSpec_JAVA.String(): &java.Platform{}, - pb.ChaincodeSpec_NODE.String(): &node.Platform{}, + "foo": fakePlatformFoo, + "bar": fakePlatformBar, })) }) + + Context("when two platforms report the same name", func() { + It("panics", func() { + fakePlatformFoo1 := &mock.Platform{} + fakePlatformFoo1.NameReturns("foo") + fakePlatformFoo2 := &mock.Platform{} + fakePlatformFoo2.NameReturns("foo") + Expect(func() { platforms.NewRegistry(fakePlatformFoo1, fakePlatformFoo2) }).To(Panic()) + }) + }) }) Describe("PackageWriterWrapper", func() { diff --git a/core/chaincode/systemchaincode_test.go b/core/chaincode/systemchaincode_test.go index 970757de648..7d182b015b2 100644 --- a/core/chaincode/systemchaincode_test.go +++ b/core/chaincode/systemchaincode_test.go @@ -15,6 +15,8 @@ import ( "github.com/hyperledger/fabric/common/crypto/tlsgen" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/container" @@ -141,6 +143,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) { }, ), sccp, + platforms.NewRegistry(&golang.Platform{}), ) pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport) diff --git a/core/committer/txvalidator/validator.go b/core/committer/txvalidator/validator.go index f957c1e79ef..b5259403ab3 100644 --- a/core/committer/txvalidator/validator.go +++ b/core/committer/txvalidator/validator.go @@ -14,6 +14,8 @@ import ( "github.com/hyperledger/fabric/common/configtx" commonerrors "github.com/hyperledger/fabric/common/errors" "github.com/hyperledger/fabric/common/flogging" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/common/sysccprovider" "github.com/hyperledger/fabric/core/common/validation" "github.com/hyperledger/fabric/core/ledger" @@ -563,7 +565,7 @@ func (v *TxValidator) getTxCCInstance(payload *common.Payload) (invokeCCIns, upg } func (v *TxValidator) getUpgradeTxInstance(chainID string, cdsBytes []byte) (*sysccprovider.ChaincodeInstance, error) { - cds, err := utils.GetChaincodeDeploymentSpec(cdsBytes) + cds, err := utils.GetChaincodeDeploymentSpec(cdsBytes, platforms.NewRegistry(&golang.Platform{})) if err != nil { return nil, err } diff --git a/core/common/ccprovider/cc_statedb_artifacts_provider.go b/core/common/ccprovider/cc_statedb_artifacts_provider.go index 8d9a70dba07..90288b5eea6 100644 --- a/core/common/ccprovider/cc_statedb_artifacts_provider.go +++ b/core/common/ccprovider/cc_statedb_artifacts_provider.go @@ -31,7 +31,7 @@ type TarFileEntry struct { // ExtractStatedbArtifactsAsTarbytes extracts the statedb artifacts from the code package tar and create a statedb artifact tar. // The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb. // This function is intented to be used during chaincode instantiate/upgrade so that statedb artifacts can be created. -func ExtractStatedbArtifactsForChaincode(ccname, ccversion string) (installed bool, statedbArtifactsTar []byte, err error) { +func ExtractStatedbArtifactsForChaincode(ccname, ccversion string, pr *platforms.Registry) (installed bool, statedbArtifactsTar []byte, err error) { ccpackage, err := GetChaincodeFromFS(ccname, ccversion) if err != nil { // TODO for now, we assume that an error indicates that the chaincode is not installed on the peer. @@ -41,16 +41,16 @@ func ExtractStatedbArtifactsForChaincode(ccname, ccversion string) (installed bo return false, nil, nil } - statedbArtifactsTar, err = ExtractStatedbArtifactsFromCCPackage(ccpackage) + statedbArtifactsTar, err = ExtractStatedbArtifactsFromCCPackage(ccpackage, pr) return true, statedbArtifactsTar, err } // ExtractStatedbArtifactsFromCCPackage extracts the statedb artifacts from the code package tar and create a statedb artifact tar. // The state db artifacts are expected to contain state db specific artifacts such as index specification in the case of couchdb. // This function is called during chaincode instantiate/upgrade (from above), and from install, so that statedb artifacts can be created. -func ExtractStatedbArtifactsFromCCPackage(ccpackage CCPackage) (statedbArtifactsTar []byte, err error) { +func ExtractStatedbArtifactsFromCCPackage(ccpackage CCPackage, pr *platforms.Registry) (statedbArtifactsTar []byte, err error) { cds := ccpackage.GetDepSpec() - metaprov, err := platforms.NewRegistry().GetMetadataProvider(cds) + metaprov, err := pr.GetMetadataProvider(cds) if err != nil { ccproviderLogger.Infof("invalid deployment spec: %s", err) return nil, fmt.Errorf("invalid deployment spec") diff --git a/core/container/controller.go b/core/container/controller.go index 25fcce9dbe0..bce05114e6f 100644 --- a/core/container/controller.go +++ b/core/container/controller.go @@ -127,12 +127,13 @@ type StartContainerReq struct { // the dockercontroller package with the CDS, which is also // undesirable. type PlatformBuilder struct { - DeploymentSpec *pb.ChaincodeDeploymentSpec + DeploymentSpec *pb.ChaincodeDeploymentSpec + PlatformRegistry *platforms.Registry } // Build a tar stream based on the CDS func (b *PlatformBuilder) Build() (io.Reader, error) { - return platforms.NewRegistry().GenerateDockerBuild(b.DeploymentSpec) + return b.PlatformRegistry.GenerateDockerBuild(b.DeploymentSpec) } func (si StartContainerReq) Do(ctxt context.Context, v VM) error { @@ -195,10 +196,10 @@ func (vmc *VMController) Process(ctxt context.Context, vmtype string, req VMCReq } // GetChaincodePackageBytes creates bytes for docker container generation using the supplied chaincode specification -func GetChaincodePackageBytes(spec *pb.ChaincodeSpec) ([]byte, error) { +func GetChaincodePackageBytes(pr *platforms.Registry, spec *pb.ChaincodeSpec) ([]byte, error) { if spec == nil || spec.ChaincodeId == nil { return nil, fmt.Errorf("invalid chaincode spec") } - return platforms.NewRegistry().GetDeploymentPayload(spec) + return pr.GetDeploymentPayload(spec) } diff --git a/core/container/controller_test.go b/core/container/controller_test.go index a5ff2c14bd3..f0c13cf1d22 100644 --- a/core/container/controller_test.go +++ b/core/container/controller_test.go @@ -10,23 +10,25 @@ import ( "testing" "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/container" pb "github.com/hyperledger/fabric/protos/peer" "github.com/stretchr/testify/assert" ) func TestVM_GetChaincodePackageBytes(t *testing.T) { - _, err := container.GetChaincodePackageBytes(nil) + _, err := container.GetChaincodePackageBytes(nil, nil) assert.Error(t, err, "GetChaincodePackageBytes did not return error when chaincode spec is nil") spec := &pb.ChaincodeSpec{ChaincodeId: nil} - _, err = container.GetChaincodePackageBytes(spec) + _, err = container.GetChaincodePackageBytes(nil, spec) assert.Error(t, err, "Error expected when GetChaincodePackageBytes is called with nil chaincode ID") assert.Contains(t, err.Error(), "invalid chaincode spec") spec = &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: nil, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs("f")}} - _, err = container.GetChaincodePackageBytes(spec) + _, err = container.GetChaincodePackageBytes(platforms.NewRegistry(&golang.Platform{}), spec) assert.Error(t, err, "GetChaincodePackageBytes did not return error when chaincode ID is nil") } diff --git a/core/container/dockercontroller/dockercontroller_test.go b/core/container/dockercontroller/dockercontroller_test.go index 554b56d7861..dd94bbd5a2b 100644 --- a/core/container/dockercontroller/dockercontroller_test.go +++ b/core/container/dockercontroller/dockercontroller_test.go @@ -26,6 +26,7 @@ import ( "github.com/hyperledger/fabric/common/ledger/testutil" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/container/ccintf" coreutil "github.com/hyperledger/fabric/core/testutil" pb "github.com/hyperledger/fabric/protos/peer" @@ -119,13 +120,13 @@ func Test_Start(t *testing.T) { ChaincodeId: &pb.ChaincodeID{Name: "ex01", Path: chaincodePath}, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs("f")}, } - codePackage, err := platforms.NewRegistry().GetDeploymentPayload(spec) + codePackage, err := platforms.NewRegistry(&golang.Platform{}).GetDeploymentPayload(spec) if err != nil { t.Fatal() } cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackage} bldr := &mockBuilder{ - buildFunc: func() (io.Reader, error) { return platforms.NewRegistry().GenerateDockerBuild(cds) }, + buildFunc: func() (io.Reader, error) { return platforms.NewRegistry(&golang.Platform{}).GenerateDockerBuild(cds) }, } // case 4: start called with builder and dockerClient.CreateContainer returns diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index 2d29f43a4ed..c829198279c 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -15,6 +15,7 @@ import ( "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/validation" @@ -96,6 +97,7 @@ type Support interface { type Endorser struct { distributePrivateData privateDataDistributor s Support + PlatformRegistry *platforms.Registry PvtRWSetAssembler } @@ -109,10 +111,11 @@ type validateResult struct { } // NewEndorserServer creates and returns a new Endorser server instance. -func NewEndorserServer(privDist privateDataDistributor, s Support) *Endorser { +func NewEndorserServer(privDist privateDataDistributor, s Support, pr *platforms.Registry) *Endorser { e := &Endorser{ distributePrivateData: privDist, s: s, + PlatformRegistry: pr, PvtRWSetAssembler: &rwSetAssembler{}, } return e @@ -154,7 +157,7 @@ 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]) + userCDS, err := putils.GetChaincodeDeploymentSpec(cis.ChaincodeSpec.Input.Args[2], e.PlatformRegistry) if err != nil { return nil, nil, err } diff --git a/core/endorser/endorser_test.go b/core/endorser/endorser_test.go index d5a81929312..411b752cab1 100644 --- a/core/endorser/endorser_test.go +++ b/core/endorser/endorser_test.go @@ -16,6 +16,8 @@ import ( mc "github.com/hyperledger/fabric/common/mocks/config" "github.com/hyperledger/fabric/common/mocks/resourcesconfig" "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/endorser" "github.com/hyperledger/fabric/core/endorser/mocks" @@ -86,7 +88,7 @@ func TestEndorserNilProp(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) pResp, err := es.ProcessProposal(context.Background(), nil) assert.Error(t, err) @@ -100,7 +102,7 @@ func TestEndorserUninvokableSysCC(t *testing.T) { GetApplicationConfigRv: &mc.MockApplication{CapabilitiesRv: &mc.MockApplicationCapabilities{}}, GetTransactionByIDErr: errors.New(""), IsSysCCAndNotInvokableExternalRv: true, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -122,7 +124,7 @@ func TestEndorserCCInvocationFailed(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -144,7 +146,7 @@ func TestEndorserNoCCDef(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -167,7 +169,7 @@ func TestEndorserBadInstPolicy(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -191,7 +193,7 @@ func TestEndorserSysCC(t *testing.T) { ExecuteResp: &pb.Response{Status: 200, Payload: utils.MarshalOrPanic(&pb.ProposalResponse{Response: &pb.Response{}})}, } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer(pvtEmptyDistributor, support, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -212,7 +214,7 @@ func TestEndorserCCInvocationError(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -233,7 +235,7 @@ func TestEndorserLSCCBadType(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -262,7 +264,7 @@ func TestEndorserDupTXId(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -285,7 +287,7 @@ func TestEndorserBadACL(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -306,7 +308,7 @@ func TestEndorserGoodPathEmptyChannel(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedPropWithCHIdAndArgs("", "ccid", "0", [][]byte{[]byte("args")}, t) @@ -328,7 +330,7 @@ func TestEndorserLSCCInitFails(t *testing.T) { }, }, ExecuteCDSError: errors.New(""), - }) + }, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -361,7 +363,7 @@ func TestEndorserLSCCDeploySysCC(t *testing.T) { }, }, SysCCMap: SysCCMap, - }) + }, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -396,7 +398,7 @@ func TestEndorserLSCCJava1(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -431,7 +433,7 @@ func TestEndorserLSCCJava2(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -463,7 +465,7 @@ func TestEndorserGoodPathWEvents(t *testing.T) { ExecuteEvent: &pb.ChaincodeEvent{}, } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer(pvtEmptyDistributor, support, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -484,7 +486,7 @@ func TestEndorserBadChannel(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedPropWithCHID("ccid", "0", "barfchain", t) @@ -508,7 +510,7 @@ func TestEndorserGoodPath(t *testing.T) { ExecuteResp: &pb.Response{Status: 200, Payload: utils.MarshalOrPanic(&pb.ProposalResponse{Response: &pb.Response{}})}, } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer(pvtEmptyDistributor, support, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -531,7 +533,7 @@ func TestEndorserLSCC(t *testing.T) { ExecuteResp: &pb.Response{Status: 200, Payload: utils.MarshalOrPanic(&pb.ProposalResponse{Response: &pb.Response{}})}, } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer(pvtEmptyDistributor, support, platforms.NewRegistry(&golang.Platform{})) cds := utils.MarshalOrPanic( &pb.ChaincodeDeploymentSpec{ @@ -579,7 +581,7 @@ func TestEndorseWithPlugin(t *testing.T) { } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer(pvtEmptyDistributor, support, platforms.NewRegistry(&golang.Platform{})) signedProp := getSignedProp("ccid", "0", t) @@ -602,7 +604,7 @@ func TestSimulateProposal(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) _, _, _, _, err := es.SimulateProposal(nil, "", "", nil, nil, nil, nil) assert.Error(t, err) @@ -624,7 +626,7 @@ func TestEndorserJavaChecks(t *testing.T) { PubSimulationResults: &rwset.TxReadWriteSet{}, }, }, - }) + }, platforms.NewRegistry(&golang.Platform{})) err := es.DisableJavaCCInst(&pb.ChaincodeID{Name: "lscc"}, &pb.ChaincodeInvocationSpec{}) assert.NoError(t, err) @@ -666,7 +668,11 @@ func TestEndorserAcquireTxSimulator(t *testing.T) { ExecuteResp: expectedResponse, } attachPluginEndorser(support) - es := endorser.NewEndorserServer(pvtEmptyDistributor, support) + es := endorser.NewEndorserServer( + pvtEmptyDistributor, + support, + platforms.NewRegistry(&golang.Platform{}), + ) t.Parallel() args := [][]byte{[]byte("args")} @@ -713,7 +719,7 @@ type support interface { func TestUserCDSSanitization(t *testing.T) { fakeSupport := &mocks.Support{} - e := endorser.NewEndorserServer(nil, fakeSupport) + e := endorser.NewEndorserServer(nil, fakeSupport, nil) userCDS := &pb.ChaincodeDeploymentSpec{ ChaincodeSpec: &pb.ChaincodeSpec{ diff --git a/core/handlers/validation/builtin/validation_logic.go b/core/handlers/validation/builtin/validation_logic.go index 1d68ee3f709..974219abf45 100644 --- a/core/handlers/validation/builtin/validation_logic.go +++ b/core/handlers/validation/builtin/validation_logic.go @@ -17,6 +17,11 @@ import ( "github.com/hyperledger/fabric/common/channelconfig" commonerrors "github.com/hyperledger/fabric/common/errors" "github.com/hyperledger/fabric/common/flogging" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/car" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" + "github.com/hyperledger/fabric/core/chaincode/platforms/java" + "github.com/hyperledger/fabric/core/chaincode/platforms/node" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/privdata" . "github.com/hyperledger/fabric/core/handlers/validation/api/capabilities" @@ -494,7 +499,17 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation( return policyErr(fmt.Errorf("Wrong number of arguments for invocation lscc(%s): received %d", lsccFunc, len(lsccArgs))) } - cdsArgs, err := utils.GetChaincodeDeploymentSpec(lsccArgs[1]) + cdsArgs, err := utils.GetChaincodeDeploymentSpec(lsccArgs[1], platforms.NewRegistry( + // XXX We should definitely _not_ have this external dependency in VSCC + // as adding a platform could cause non-determinism. This is yet another + // reason why all of this custom LSCC validation at commit time has no + // long term hope of staying deterministic and needs to be removed. + &golang.Platform{}, + &node.Platform{}, + &java.Platform{}, + &car.Platform{}, + )) + if err != nil { return policyErr(fmt.Errorf("GetChaincodeDeploymentSpec error %s", err)) } diff --git a/core/handlers/validation/builtin/validation_logic_test.go b/core/handlers/validation/builtin/validation_logic_test.go index cbb0cace9e0..06465071280 100644 --- a/core/handlers/validation/builtin/validation_logic_test.go +++ b/core/handlers/validation/builtin/validation_logic_test.go @@ -22,6 +22,8 @@ import ( "github.com/hyperledger/fabric/common/mocks/scc" "github.com/hyperledger/fabric/common/util" aclmocks "github.com/hyperledger/fabric/core/aclmgmt/mocks" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/committer/txvalidator" mocks2 "github.com/hyperledger/fabric/core/committer/txvalidator/mocks" @@ -424,7 +426,7 @@ func TestRWSetTooBig(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -483,7 +485,7 @@ func TestValidateDeployFail(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -741,7 +743,7 @@ func TestAlreadyDeployed(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -838,7 +840,7 @@ func TestValidateDeployOK(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -887,7 +889,7 @@ func TestValidateDeployWithCollection(t *testing.T) { }) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -978,7 +980,7 @@ func TestValidateDeployWithCollection(t *testing.T) { v = newValidationInstance(state) - lccc = lscc.New(mp, mockAclProvider) + lccc = lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc = shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1002,7 +1004,7 @@ func TestValidateDeployWithPolicies(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1073,7 +1075,7 @@ func TestInvalidUpgrade(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1114,7 +1116,7 @@ func TestValidateUpgradeOK(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1180,7 +1182,7 @@ func TestInvalidateUpgradeBadVersion(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1252,7 +1254,7 @@ func validateUpgradeWithCollection(t *testing.T, V1_2Validation bool) { }) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1440,7 +1442,7 @@ func TestValidateUpgradeWithPoliciesOK(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1529,7 +1531,7 @@ func validateUpgradeWithNewFailAllIP(t *testing.T, v11capability, expecterr bool v := newCustomValidationInstance(qec, capabilities) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State @@ -1609,7 +1611,7 @@ func TestValidateUpgradeWithPoliciesFail(t *testing.T) { v := newValidationInstance(state) mockAclProvider := &aclmocks.MockACLProvider{} - lccc := lscc.New(mp, mockAclProvider) + lccc := lscc.New(mp, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) stublccc := shim.NewMockStub("lscc", lccc) state["lscc"] = stublccc.State diff --git a/core/ledger/cceventmgmt/defs.go b/core/ledger/cceventmgmt/defs.go index 770343dd315..c74bacc0ad1 100644 --- a/core/ledger/cceventmgmt/defs.go +++ b/core/ledger/cceventmgmt/defs.go @@ -9,6 +9,7 @@ package cceventmgmt import ( "fmt" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/sysccprovider" ) @@ -50,6 +51,7 @@ type ChaincodeInfoProvider interface { } type chaincodeInfoProviderImpl struct { + PlatformRegistry *platforms.Registry } // IsChaincodeDeployed implements function in the interface ChaincodeInfoProvider @@ -59,5 +61,5 @@ func (p *chaincodeInfoProviderImpl) IsChaincodeDeployed(chainid string, chaincod // RetrieveChaincodeArtifacts implements function in the interface ChaincodeInfoProvider func (p *chaincodeInfoProviderImpl) RetrieveChaincodeArtifacts(chaincodeDefinition *ChaincodeDefinition) (installed bool, dbArtifactsTar []byte, err error) { - return ccprovider.ExtractStatedbArtifactsForChaincode(chaincodeDefinition.Name, chaincodeDefinition.Version) + return ccprovider.ExtractStatedbArtifactsForChaincode(chaincodeDefinition.Name, chaincodeDefinition.Version, p.PlatformRegistry) } diff --git a/core/ledger/cceventmgmt/mgr.go b/core/ledger/cceventmgmt/mgr.go index 2286e444b6e..36069ce1649 100644 --- a/core/ledger/cceventmgmt/mgr.go +++ b/core/ledger/cceventmgmt/mgr.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/hyperledger/fabric/common/flogging" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/sysccprovider" ) @@ -18,8 +19,8 @@ var logger = flogging.MustGetLogger("cceventmgmt") var mgr *Mgr // Initialize initializes event mgmt -func Initialize() { - initialize(&chaincodeInfoProviderImpl{}) +func Initialize(pr *platforms.Registry) { + initialize(&chaincodeInfoProviderImpl{PlatformRegistry: pr}) } func initialize(ccInfoProvider ChaincodeInfoProvider) { diff --git a/core/ledger/kvledger/example/main/example.go b/core/ledger/kvledger/example/main/example.go index 70810a79874..72564125138 100644 --- a/core/ledger/kvledger/example/main/example.go +++ b/core/ledger/kvledger/example/main/example.go @@ -21,6 +21,8 @@ import ( "os" configtxtest "github.com/hyperledger/fabric/common/configtx/test" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/kvledger/example" "github.com/hyperledger/fabric/core/ledger/ledgerconfig" @@ -53,7 +55,7 @@ func init() { // Note, if subledgers are supported in the future, // the various ledgers could be created/managed at this level cleanup() - ledgermgmt.Initialize(nil) + ledgermgmt.Initialize(nil, platforms.NewRegistry(&golang.Platform{})) var err error gb, _ := configtxtest.MakeGenesisBlock(ledgerID) diff --git a/core/ledger/kvledger/marble_example/main/marble_example.go b/core/ledger/kvledger/marble_example/main/marble_example.go index cb6432fd649..6b4c53084e6 100644 --- a/core/ledger/kvledger/marble_example/main/marble_example.go +++ b/core/ledger/kvledger/marble_example/main/marble_example.go @@ -22,6 +22,8 @@ import ( "os" configtxtest "github.com/hyperledger/fabric/common/configtx/test" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/kvledger/example" "github.com/hyperledger/fabric/core/ledger/ledgerconfig" @@ -54,7 +56,7 @@ func init() { testutil.SetupCoreYAMLConfig() cleanup() - ledgermgmt.Initialize(nil) + ledgermgmt.Initialize(nil, platforms.NewRegistry(&golang.Platform{})) var err error gb, _ := configtxtest.MakeGenesisBlock(ledgerID) peerLedger, err = ledgermgmt.CreateLedger(gb) diff --git a/core/ledger/ledgermgmt/ledger_mgmt.go b/core/ledger/ledgermgmt/ledger_mgmt.go index 35031c34eb5..66f0cbbeee9 100644 --- a/core/ledger/ledgermgmt/ledger_mgmt.go +++ b/core/ledger/ledgermgmt/ledger_mgmt.go @@ -25,6 +25,7 @@ import ( "fmt" "github.com/hyperledger/fabric/common/flogging" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/customtx" "github.com/hyperledger/fabric/core/ledger/kvledger" @@ -47,20 +48,20 @@ var initialized bool var once sync.Once // Initialize initializes ledgermgmt -func Initialize(customTxProcessors customtx.Processors) { +func Initialize(customTxProcessors customtx.Processors, pr *platforms.Registry) { once.Do(func() { - initialize(customTxProcessors, nil) + initialize(customTxProcessors, nil, pr) }) } -func initialize(customTxProcessors customtx.Processors, statelisteners []ledger.StateListener) { +func initialize(customTxProcessors customtx.Processors, statelisteners []ledger.StateListener, pr *platforms.Registry) { logger.Info("Initializing ledger mgmt") lock.Lock() defer lock.Unlock() initialized = true openedLedgers = make(map[string]ledger.PeerLedger) customtx.Initialize(customTxProcessors) - cceventmgmt.Initialize() + cceventmgmt.Initialize(pr) finalStateListeners := addListenerForCCEventsHandler(statelisteners) provider, err := kvledger.NewProvider() if err != nil { diff --git a/core/ledger/ledgermgmt/ledger_mgmt_test.go b/core/ledger/ledgermgmt/ledger_mgmt_test.go index 5b0abfcf64c..050c3ce667d 100644 --- a/core/ledger/ledgermgmt/ledger_mgmt_test.go +++ b/core/ledger/ledgermgmt/ledger_mgmt_test.go @@ -24,6 +24,8 @@ import ( "github.com/hyperledger/fabric/common/configtx/test" "github.com/hyperledger/fabric/common/ledger/testutil" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/ledger" "github.com/spf13/viper" ) @@ -85,7 +87,7 @@ func TestLedgerMgmt(t *testing.T) { Close() // Restart ledger mgmt with existing ledgers - Initialize(nil) + Initialize(nil, platforms.NewRegistry(&golang.Platform{})) l, err = OpenLedger(ledgerID) testutil.AssertNoError(t, err, "") Close() diff --git a/core/ledger/ledgermgmt/ledger_mgmt_test_exports.go b/core/ledger/ledgermgmt/ledger_mgmt_test_exports.go index f398e97147f..f3e39272f3d 100644 --- a/core/ledger/ledgermgmt/ledger_mgmt_test_exports.go +++ b/core/ledger/ledgermgmt/ledger_mgmt_test_exports.go @@ -19,6 +19,8 @@ package ledgermgmt import ( "os" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/ledger/customtx" "github.com/hyperledger/fabric/core/ledger/ledgerconfig" @@ -29,14 +31,14 @@ import ( // InitializeTestEnv initializes ledgermgmt for tests func InitializeTestEnv() { remove() - initialize(nil, nil) + initialize(nil, nil, platforms.NewRegistry(&golang.Platform{})) } // InitializeTestEnvWithCustomProcessors initializes ledgermgmt for tests with the supplied custom tx processors func InitializeTestEnvWithCustomProcessors(customTxProcessors customtx.Processors) { remove() customtx.InitializeTestEnv(customTxProcessors) - initialize(customTxProcessors, nil) + initialize(customTxProcessors, nil, platforms.NewRegistry(&golang.Platform{})) } // CleanupTestEnv closes the ledgermagmt and removes the store directory diff --git a/core/peer/peer.go b/core/peer/peer.go index d5fdd8d961f..bf8ae81e1e1 100644 --- a/core/peer/peer.go +++ b/core/peer/peer.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/fabric/common/ledger/blockledger" fileledger "github.com/hyperledger/fabric/common/ledger/blockledger/file" "github.com/hyperledger/fabric/common/policies" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/comm" "github.com/hyperledger/fabric/core/committer" "github.com/hyperledger/fabric/core/committer/txvalidator" @@ -188,7 +189,7 @@ var validationWorkersSemaphore *semaphore.Weighted // Initialize sets up any chains that the peer has from the persistence. This // function should be called at the start up when the ledger and gossip // ready -func Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, pm txvalidator.PluginMapper) { +func Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, pm txvalidator.PluginMapper, pr *platforms.Registry) { nWorkers := viper.GetInt("peer.validatorPoolSize") if nWorkers <= 0 { nWorkers = runtime.NumCPU() @@ -200,7 +201,7 @@ func Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccp var cb *common.Block var ledger ledger.PeerLedger - ledgermgmt.Initialize(ConfigTxProcessors) + ledgermgmt.Initialize(ConfigTxProcessors, pr) ledgerIds, err := ledgermgmt.GetLedgerIDs() if err != nil { panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err)) diff --git a/core/peer/peer_impl.go b/core/peer/peer_impl.go index bd49684527f..60133920ce5 100644 --- a/core/peer/peer_impl.go +++ b/core/peer/peer_impl.go @@ -9,6 +9,7 @@ package peer import ( "github.com/hyperledger/fabric/common/channelconfig" "github.com/hyperledger/fabric/common/policies" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/committer/txvalidator" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/sysccprovider" @@ -29,7 +30,7 @@ type Operations interface { GetMSPIDs(cid string) []string GetPolicyManager(cid string) policies.Manager InitChain(cid string) - Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, pm txvalidator.PluginMapper) + Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, pm txvalidator.PluginMapper, pr *platforms.Registry) } type peerImpl struct { @@ -41,7 +42,7 @@ type peerImpl struct { getMSPIDs func(cid string) []string getPolicyManager func(cid string) policies.Manager initChain func(cid string) - initialize func(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, mapper txvalidator.PluginMapper) + initialize func(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, mapper txvalidator.PluginMapper, pr *platforms.Registry) } // Default provides in implementation of the Peer interface that provides @@ -72,6 +73,6 @@ func (p *peerImpl) GetLedger(cid string) ledger.PeerLedger { return p.getL func (p *peerImpl) GetMSPIDs(cid string) []string { return p.getMSPIDs(cid) } func (p *peerImpl) GetPolicyManager(cid string) policies.Manager { return p.getPolicyManager(cid) } func (p *peerImpl) InitChain(cid string) { p.initChain(cid) } -func (p *peerImpl) Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, mapper txvalidator.PluginMapper) { - p.initialize(init, ccp, sccp, mapper) +func (p *peerImpl) Initialize(init func(string), ccp ccprovider.ChaincodeProvider, sccp sysccprovider.SystemChaincodeProvider, mapper txvalidator.PluginMapper, pr *platforms.Registry) { + p.initialize(init, ccp, sccp, mapper, pr) } diff --git a/core/peer/peer_test.go b/core/peer/peer_test.go index bafa94b801b..db922519ecf 100644 --- a/core/peer/peer_test.go +++ b/core/peer/peer_test.go @@ -15,6 +15,7 @@ import ( configtxtest "github.com/hyperledger/fabric/common/configtx/test" "github.com/hyperledger/fabric/common/localmsp" mscc "github.com/hyperledger/fabric/common/mocks/scc" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/comm" "github.com/hyperledger/fabric/core/committer/txvalidator" "github.com/hyperledger/fabric/core/deliverservice" @@ -84,14 +85,14 @@ func TestInitialize(t *testing.T) { cleanup := setupPeerFS(t) defer cleanup() - Initialize(nil, &ccprovider.MockCcProviderImpl{}, (&mscc.MocksccProviderFactory{}).NewSystemChaincodeProvider(), txvalidator.MapBasedPluginMapper(map[string]validation.PluginFactory{})) + Initialize(nil, &ccprovider.MockCcProviderImpl{}, (&mscc.MocksccProviderFactory{}).NewSystemChaincodeProvider(), txvalidator.MapBasedPluginMapper(map[string]validation.PluginFactory{}), nil) } func TestCreateChainFromBlock(t *testing.T) { cleanup := setupPeerFS(t) defer cleanup() - Initialize(nil, &ccprovider.MockCcProviderImpl{}, (&mscc.MocksccProviderFactory{}).NewSystemChaincodeProvider(), txvalidator.MapBasedPluginMapper(map[string]validation.PluginFactory{})) + Initialize(nil, &ccprovider.MockCcProviderImpl{}, (&mscc.MocksccProviderFactory{}).NewSystemChaincodeProvider(), txvalidator.MapBasedPluginMapper(map[string]validation.PluginFactory{}), &platforms.Registry{}) testChainID := fmt.Sprintf("mytestchainid-%d", rand.Int()) block, err := configtxtest.MakeGenesisBlock(testChainID) if err != nil { diff --git a/core/scc/cscc/configure_test.go b/core/scc/cscc/configure_test.go index 8d1c69c7fc1..109f0803283 100644 --- a/core/scc/cscc/configure_test.go +++ b/core/scc/cscc/configure_test.go @@ -29,6 +29,8 @@ import ( "github.com/hyperledger/fabric/core/aclmgmt/resources" "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/container" @@ -229,6 +231,7 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { }, ), mp, + platforms.NewRegistry(&golang.Platform{}), ) // Init the policy checker diff --git a/core/scc/importsysccs.go b/core/scc/importsysccs.go index a2f991e6ce9..f294e170201 100644 --- a/core/scc/importsysccs.go +++ b/core/scc/importsysccs.go @@ -9,13 +9,14 @@ package scc import ( //import system chaincodes here "github.com/hyperledger/fabric/core/aclmgmt" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/scc/cscc" "github.com/hyperledger/fabric/core/scc/lscc" "github.com/hyperledger/fabric/core/scc/qscc" ) -func builtInSystemChaincodes(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider) []*SystemChaincode { +func builtInSystemChaincodes(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider, pr *platforms.Registry) []*SystemChaincode { return []*SystemChaincode{ { Enabled: true, @@ -30,7 +31,7 @@ func builtInSystemChaincodes(ccp ccprovider.ChaincodeProvider, p *Provider, aclP Name: "lscc", Path: "github.com/hyperledger/fabric/core/scc/lscc", InitArgs: nil, - Chaincode: lscc.New(p, aclProvider), + Chaincode: lscc.New(p, aclProvider, pr), InvokableExternal: true, // lscc is invoked to deploy new chaincodes InvokableCC2CC: true, // lscc can be invoked by other chaincodes }, diff --git a/core/scc/lscc/lscc.go b/core/scc/lscc/lscc.go index d1e1d65166b..853c54d048a 100644 --- a/core/scc/lscc/lscc.go +++ b/core/scc/lscc/lscc.go @@ -15,6 +15,7 @@ import ( "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/core/aclmgmt" "github.com/hyperledger/fabric/core/aclmgmt/resources" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/chaincode/platforms/ccmetadata" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" @@ -129,16 +130,19 @@ type lifeCycleSysCC struct { // support provides the implementation of several // static functions support FilesystemSupport + + PlatformRegistry *platforms.Registry } // New creates a new instance of the LSCC // Typically there is only one of these per peer -func New(sccp sysccprovider.SystemChaincodeProvider, aclProvider aclmgmt.ACLProvider) *lifeCycleSysCC { +func New(sccp sysccprovider.SystemChaincodeProvider, aclProvider aclmgmt.ACLProvider, platformRegistry *platforms.Registry) *lifeCycleSysCC { return &lifeCycleSysCC{ - support: &supportImpl{}, - policyChecker: policyprovider.GetPolicyChecker(), - sccprovider: sccp, - aclProvider: aclProvider, + support: &supportImpl{}, + policyChecker: policyprovider.GetPolicyChecker(), + sccprovider: sccp, + aclProvider: aclProvider, + PlatformRegistry: platformRegistry, } } @@ -499,7 +503,7 @@ func (lscc *lifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccb } // Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions - statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack) + statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack, lscc.PlatformRegistry) if err != nil { return err } @@ -779,7 +783,7 @@ func (lscc *lifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response } depSpec := args[2] - cds, err := utils.GetChaincodeDeploymentSpec(depSpec) + cds, err := utils.GetChaincodeDeploymentSpec(depSpec, lscc.PlatformRegistry) if err != nil { return shim.Error(err.Error()) } diff --git a/core/scc/lscc/lscc_test.go b/core/scc/lscc/lscc_test.go index 7940f30e76f..0c0d0de1b50 100644 --- a/core/scc/lscc/lscc_test.go +++ b/core/scc/lscc/lscc_test.go @@ -23,6 +23,8 @@ import ( "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/aclmgmt/mocks" "github.com/hyperledger/fabric/core/aclmgmt/resources" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" cutil "github.com/hyperledger/fabric/core/container/util" @@ -44,7 +46,7 @@ import ( ) func constructDeploymentSpec(name string, path string, version string, initArgs [][]byte, createInvalidIndex bool, createFS bool, scc *lifeCycleSysCC) (*pb.ChaincodeDeploymentSpec, error) { - spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: path, Version: version}, Input: &pb.ChaincodeInput{Args: initArgs}} + spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: name, Path: path, Version: version}, Input: &pb.ChaincodeInput{Args: initArgs}} codePackageBytes := bytes.NewBuffer(nil) gz := gzip.NewWriter(codePackageBytes) @@ -96,9 +98,9 @@ func constructDeploymentSpec(name string, path string, version string, initArgs func TestInstall(t *testing.T) { // Initialize cceventmgmt Mgr // TODO cceventmgmt singleton should be refactored out of peer in the future. See CR 16549 for details. - cceventmgmt.Initialize() + cceventmgmt.Initialize(platforms.NewRegistry(&golang.Platform{})) - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -179,7 +181,7 @@ func TestDeploy(t *testing.T) { testDeploy(t, "example02", "1{}0", path, false, false, true, InvalidVersionErr("1{}0").Error(), nil, nil, nil) testDeploy(t, "example02", "0", path, true, true, true, EmptyChaincodeNameErr("").Error(), nil, nil, nil) - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -200,7 +202,7 @@ func TestDeploy(t *testing.T) { testDeploy(t, "example02", "1.0", path, false, false, true, "", scc, stub, nil) testDeploy(t, "example02", "1.0", path, false, false, true, "chaincode with name 'example02' already exists", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -209,7 +211,7 @@ func TestDeploy(t *testing.T) { testDeploy(t, "example02", "1.0", path, false, false, true, "barf", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -218,7 +220,7 @@ func TestDeploy(t *testing.T) { testDeploy(t, "example02", "1.0", path, false, false, true, "barf", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -239,7 +241,7 @@ func TestDeploy(t *testing.T) { }, }).NewSystemChaincodeProvider().(*mscc.MocksccProviderImpl) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -266,7 +268,7 @@ func TestDeploy(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, ccpBytes) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -282,7 +284,7 @@ func TestDeploy(t *testing.T) { assert.Equal(t, true, ok) assert.Equal(t, ccpBytes, actualccpBytes) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -321,7 +323,7 @@ func createCollectionConfig(collectionName string, signaturePolicyEnvelope *comm func testDeploy(t *testing.T, ccname string, version string, path string, forceBlankCCName bool, forceBlankVersion bool, install bool, expectedErrorMsg string, scc *lifeCycleSysCC, stub *shim.MockStub, collectionConfigBytes []byte) { if scc == nil { - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -436,7 +438,7 @@ func TestUpgrade(t *testing.T) { testUpgrade(t, "example02", "0", "example*02", "1{}0", path, InvalidChaincodeNameErr("example*02").Error(), nil, nil, nil) testUpgrade(t, "example02", "0", "", "1", path, EmptyChaincodeNameErr("").Error(), nil, nil, nil) - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -446,7 +448,7 @@ func TestUpgrade(t *testing.T) { testUpgrade(t, "example02", "0", "example02", "1", path, "barf", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -454,7 +456,7 @@ func TestUpgrade(t *testing.T) { testUpgrade(t, "example02", "0", "example02", "1", path, "instantiation policy missing", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -465,7 +467,7 @@ func TestUpgrade(t *testing.T) { testUpgrade(t, "example02", "0", "example02", "1", path, "barf", scc, stub, nil) - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -486,7 +488,7 @@ func TestUpgrade(t *testing.T) { }, }).NewSystemChaincodeProvider().(*mscc.MocksccProviderImpl) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -520,7 +522,7 @@ func TestUpgrade(t *testing.T) { }, }).NewSystemChaincodeProvider().(*mscc.MocksccProviderImpl) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -534,7 +536,7 @@ func TestUpgrade(t *testing.T) { _, ok := stub.State["example02"] assert.Equal(t, true, ok) - scc = New(mocksccProvider, mockAclProvider) + scc = New(mocksccProvider, mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res = stub.MockInit("1", nil) @@ -556,7 +558,7 @@ func TestUpgrade(t *testing.T) { func testUpgrade(t *testing.T, ccname string, version string, newccname string, newversion string, path string, expectedErrorMsg string, scc *lifeCycleSysCC, stub *shim.MockStub, collectionConfigBytes []byte) { if scc == nil { - scc = New(NewMockProvider(), mockAclProvider) + scc = New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub = shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -618,7 +620,7 @@ func testUpgrade(t *testing.T, ccname string, version string, newccname string, } func TestFunctionsWithAliases(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -668,7 +670,7 @@ func TestFunctionsWithAliases(t *testing.T) { } func TestGetChaincodes(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) stub.ChannelID = "test" @@ -699,7 +701,7 @@ func TestGetChaincodes(t *testing.T) { } func TestGetInstalledChaincodes(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) scc.support = &lscc.MockSupport{} stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -757,7 +759,7 @@ func TestGetInstalledChaincodes(t *testing.T) { } func TestNewLifeCycleSysCC(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) assert.NotNil(t, scc) stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -769,7 +771,7 @@ func TestNewLifeCycleSysCC(t *testing.T) { } func TestGetChaincodeData(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) assert.NotNil(t, scc) stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) @@ -784,7 +786,7 @@ func TestGetChaincodeData(t *testing.T) { } func TestExecuteInstall(t *testing.T) { - scc := New(NewMockProvider(), mockAclProvider) + scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{})) assert.NotNil(t, scc) stub := shim.NewMockStub("lscc", scc) res := stub.MockInit("1", nil) diff --git a/core/scc/register.go b/core/scc/register.go index b9295f2a638..a7c254b3cd5 100644 --- a/core/scc/register.go +++ b/core/scc/register.go @@ -10,10 +10,11 @@ package scc import ( "github.com/hyperledger/fabric/core/aclmgmt" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" ) // CreateSysCCs creates all of the system chaincodes which are compiled into fabric -func CreateSysCCs(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider) []*SystemChaincode { - return builtInSystemChaincodes(ccp, p, aclProvider) +func CreateSysCCs(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider, pr *platforms.Registry) []*SystemChaincode { + return builtInSystemChaincodes(ccp, p, aclProvider, pr) } diff --git a/core/scc/register_pluginsenabled.go b/core/scc/register_pluginsenabled.go index 39ac861e441..b72ed2fa1da 100644 --- a/core/scc/register_pluginsenabled.go +++ b/core/scc/register_pluginsenabled.go @@ -11,11 +11,12 @@ package scc import ( "github.com/hyperledger/fabric/core/aclmgmt" + "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/common/ccprovider" ) // CreateSysCCs creates all of the system chaincodes which are compiled into fabric // as well as those which are loaded by plugin -func CreateSysCCs(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider) []*SystemChaincode { - return append(builtInSystemChaincodes(ccp, p, aclProvider), loadSysCCs(p)...) +func CreateSysCCs(ccp ccprovider.ChaincodeProvider, p *Provider, aclProvider aclmgmt.ACLProvider, pr *platforms.Registry) []*SystemChaincode { + return append(builtInSystemChaincodes(ccp, p, aclProvider, pr), loadSysCCs(p)...) } diff --git a/core/scc/scc_test.go b/core/scc/scc_test.go index 38ffb240963..7768197f8f2 100644 --- a/core/scc/scc_test.go +++ b/core/scc/scc_test.go @@ -29,7 +29,7 @@ func newTestProvider() *Provider { ccp := &ccprovider2.MockCcProviderImpl{} mockAclProvider := &aclmocks.MockACLProvider{} p := NewProvider(peer.Default, peer.DefaultSupport, inproccontroller.NewRegistry()) - for _, cc := range CreateSysCCs(ccp, p, mockAclProvider) { + for _, cc := range CreateSysCCs(ccp, p, mockAclProvider, nil) { p.RegisterSysCC(cc) } return p @@ -93,7 +93,7 @@ func TestSccProviderImpl_GetQueryExecutorForLedger(t *testing.T) { func TestRegisterSysCC(t *testing.T) { ccp := &ccprovider2.MockCcProviderImpl{} mockAclProvider := &aclmocks.MockACLProvider{} - assert.NotPanics(t, func() { CreateSysCCs(ccp, newTestProvider(), mockAclProvider) }, "expected successful init") + assert.NotPanics(t, func() { CreateSysCCs(ccp, newTestProvider(), mockAclProvider, nil) }, "expected successful init") p := &Provider{ Registrar: inproccontroller.NewRegistry(), diff --git a/peer/chaincode/chaincode.go b/peer/chaincode/chaincode.go index 473f8e9bed7..0217a1282b6 100644 --- a/peer/chaincode/chaincode.go +++ b/peer/chaincode/chaincode.go @@ -11,6 +11,11 @@ import ( "time" "github.com/hyperledger/fabric/common/flogging" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/car" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" + "github.com/hyperledger/fabric/core/chaincode/platforms/java" + "github.com/hyperledger/fabric/core/chaincode/platforms/node" "github.com/hyperledger/fabric/peer/common" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -23,6 +28,17 @@ const ( var logger = flogging.MustGetLogger("chaincodeCmd") +// XXX This is a terrible singleton hack, however +// it simply making a latent dependency explicit. +// It should be removed along with the other package +// scoped variables +var platformRegistry = platforms.NewRegistry( + &golang.Platform{}, + &car.Platform{}, + &java.Platform{}, + &node.Platform{}, +) + func addFlags(cmd *cobra.Command) { common.AddOrdererFlags(cmd) flags := cmd.PersistentFlags() diff --git a/peer/chaincode/common.go b/peer/chaincode/common.go index 0678aa2f149..a0f9bb74a25 100644 --- a/peer/chaincode/common.go +++ b/peer/chaincode/common.go @@ -20,7 +20,6 @@ import ( "github.com/hyperledger/fabric/common/localmsp" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode" - "github.com/hyperledger/fabric/core/chaincode/platforms" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/container" "github.com/hyperledger/fabric/msp" @@ -44,7 +43,7 @@ func checkSpec(spec *pb.ChaincodeSpec) error { return errors.New("expected chaincode specification, nil received") } - return platforms.NewRegistry().ValidateSpec(spec) + return platformRegistry.ValidateSpec(spec) } // getChaincodeDeploymentSpec get chaincode deployment spec given the chaincode spec @@ -56,7 +55,7 @@ func getChaincodeDeploymentSpec(spec *pb.ChaincodeSpec, crtPkg bool) (*pb.Chainc return nil, err } - codePackageBytes, err = container.GetChaincodePackageBytes(spec) + codePackageBytes, err = container.GetChaincodePackageBytes(platformRegistry, spec) if err != nil { err = errors.WithMessage(err, "error getting chaincode package bytes") return nil, err diff --git a/peer/chaincode/install.go b/peer/chaincode/install.go index c77d9c16709..b9f49d9692b 100644 --- a/peer/chaincode/install.go +++ b/peer/chaincode/install.go @@ -141,7 +141,7 @@ func getPackageFromFile(ccpackfile string) (proto.Message, *pb.ChaincodeDeployme } //...and get the CDS at last - cds, err = utils.GetChaincodeDeploymentSpec(sCDS.ChaincodeDeploymentSpec) + cds, err = utils.GetChaincodeDeploymentSpec(sCDS.ChaincodeDeploymentSpec, platformRegistry) if err != nil { return nil, nil, fmt.Errorf("error extracting chaincode deployment spec(%s)", err) } diff --git a/peer/node/start.go b/peer/node/start.go index d51aed83aba..814ccac9e54 100644 --- a/peer/node/start.go +++ b/peer/node/start.go @@ -30,6 +30,11 @@ import ( "github.com/hyperledger/fabric/core/cclifecycle" "github.com/hyperledger/fabric/core/chaincode" "github.com/hyperledger/fabric/core/chaincode/accesscontrol" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/car" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" + "github.com/hyperledger/fabric/core/chaincode/platforms/java" + "github.com/hyperledger/fabric/core/chaincode/platforms/node" "github.com/hyperledger/fabric/core/comm" "github.com/hyperledger/fabric/core/committer/txvalidator" "github.com/hyperledger/fabric/core/common/ccprovider" @@ -149,8 +154,15 @@ func serve(args []string) error { aclmgmt.ResourceGetter(peer.GetStableChannelConfig), ) + pr := platforms.NewRegistry( + &golang.Platform{}, + &node.Platform{}, + &java.Platform{}, + &car.Platform{}, + ) + //initialize resource management exit - ledgermgmt.Initialize(peer.ConfigTxProcessors) + ledgermgmt.Initialize(peer.ConfigTxProcessors, pr) // Parameter overrides must be processed before any parameters are // cached. Failures to cache cause the server to terminate immediately. @@ -233,7 +245,7 @@ func serve(args []string) error { if err != nil { logger.Panicf("Failed to create chaincode server: %s", err) } - chaincodeSupport, ccp, sccp := registerChaincodeSupport(ccSrv, ccEndpoint, ca, aclProvider) + chaincodeSupport, ccp, sccp := registerChaincodeSupport(ccSrv, ccEndpoint, ca, aclProvider, pr) go ccSrv.Start() logger.Debugf("Running peer") @@ -278,7 +290,7 @@ func serve(args []string) error { SigningIdentityFetcher: signingIdentityFetcher, }) endorserSupport.PluginEndorser = pluginEndorser - serverEndorser := endorser.NewEndorserServer(privDataDist, endorserSupport) + serverEndorser := endorser.NewEndorserServer(privDataDist, endorserSupport, pr) auth := authHandler.ChainFilters(serverEndorser, authFilters...) // Register the Endorser server pb.RegisterEndorserServer(peerServer.Server(), auth) @@ -368,7 +380,7 @@ func serve(args []string) error { logger.Panicf("Failed subscribing to chaincode lifecycle updates") } cceventmgmt.GetMgr().Register(cid, sub) - }, ccp, sccp, txvalidator.MapBasedPluginMapper(validationPluginsByName)) + }, ccp, sccp, txvalidator.MapBasedPluginMapper(validationPluginsByName), pr) if viper.GetBool("peer.discovery.enabled") { registerDiscoveryService(peerServer, policyMgr, lifecycle) @@ -602,7 +614,7 @@ func computeChaincodeEndpoint(peerHostname string) (ccEndpoint string, err error //NOTE - when we implement JOIN we will no longer pass the chainID as param //The chaincode support will come up without registering system chaincodes //which will be registered only during join phase. -func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca tlsgen.CA, aclProvider aclmgmt.ACLProvider) (*chaincode.ChaincodeSupport, ccprovider.ChaincodeProvider, *scc.Provider) { +func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca tlsgen.CA, aclProvider aclmgmt.ACLProvider, pr *platforms.Registry) (*chaincode.ChaincodeSupport, ccprovider.ChaincodeProvider, *scc.Provider) { //get user mode userRunsCC := chaincode.IsDevMode() tlsEnabled := viper.GetBool("peer.tls.enabled") @@ -626,6 +638,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca inproccontroller.ContainerType: ipRegistry, }), sccp, + pr, ) ccp := chaincode.NewProvider(chaincodeSupport) @@ -635,7 +648,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca } //Now that chaincode is initialized, register all system chaincodes. - sccs := scc.CreateSysCCs(ccp, sccp, aclProvider) + sccs := scc.CreateSysCCs(ccp, sccp, aclProvider, pr) for _, cc := range sccs { sccp.RegisterSysCC(cc) } diff --git a/protos/utils/proputils.go b/protos/utils/proputils.go index 5c956b49d66..79920357809 100644 --- a/protos/utils/proputils.go +++ b/protos/utils/proputils.go @@ -148,7 +148,7 @@ func GetProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) { } // GetChaincodeDeploymentSpec returns a ChaincodeDeploymentSpec given args -func GetChaincodeDeploymentSpec(code []byte) (*peer.ChaincodeDeploymentSpec, error) { +func GetChaincodeDeploymentSpec(code []byte, pr *platforms.Registry) (*peer.ChaincodeDeploymentSpec, error) { cds := &peer.ChaincodeDeploymentSpec{} err := proto.Unmarshal(code, cds) if err != nil { @@ -156,7 +156,7 @@ func GetChaincodeDeploymentSpec(code []byte) (*peer.ChaincodeDeploymentSpec, err } // FAB-2122: Validate the CDS according to platform specific requirements - return cds, platforms.NewRegistry().ValidateDeploymentSpec(cds) + return cds, pr.ValidateDeploymentSpec(cds) } // GetChaincodeAction gets the ChaincodeAction given chaicnode action bytes diff --git a/protos/utils/proputils_test.go b/protos/utils/proputils_test.go index e4794c43369..aea1ee3d5c5 100644 --- a/protos/utils/proputils_test.go +++ b/protos/utils/proputils_test.go @@ -17,6 +17,8 @@ import ( "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/platforms" + "github.com/hyperledger/fabric/core/chaincode/platforms/golang" "github.com/hyperledger/fabric/msp" mspmgmt "github.com/hyperledger/fabric/msp/mgmt" "github.com/hyperledger/fabric/msp/mgmt/testtools" @@ -157,7 +159,9 @@ func TestGetNonce(t *testing.T) { } func TestGetChaincodeDeploymentSpec(t *testing.T) { - _, err := utils.GetChaincodeDeploymentSpec([]byte("bad spec")) + pr := platforms.NewRegistry(&golang.Platform{}) + + _, err := utils.GetChaincodeDeploymentSpec([]byte("bad spec"), pr) assert.Error(t, err, "Expected error with malformed spec") cds, _ := proto.Marshal(&pb.ChaincodeDeploymentSpec{ @@ -165,7 +169,7 @@ func TestGetChaincodeDeploymentSpec(t *testing.T) { Type: pb.ChaincodeSpec_GOLANG, }, }) - _, err = utils.GetChaincodeDeploymentSpec(cds) + _, err = utils.GetChaincodeDeploymentSpec(cds, pr) assert.NoError(t, err, "Unexpected error getting deployment spec") cds, _ = proto.Marshal(&pb.ChaincodeDeploymentSpec{ @@ -173,7 +177,7 @@ func TestGetChaincodeDeploymentSpec(t *testing.T) { Type: pb.ChaincodeSpec_UNDEFINED, }, }) - _, err = utils.GetChaincodeDeploymentSpec(cds) + _, err = utils.GetChaincodeDeploymentSpec(cds, pr) assert.Error(t, err, "Expected error with invalid spec type") }