Skip to content

Commit

Permalink
FAB-10825 Make platform latent dependency explicit
Browse files Browse the repository at this point in the history
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 <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Jul 3, 2018
1 parent 9c774de commit 9112ebf
Show file tree
Hide file tree
Showing 45 changed files with 354 additions and 166 deletions.
11 changes: 7 additions & 4 deletions core/chaincode/chaincode_support.go
Expand Up @@ -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"
Expand Down Expand Up @@ -55,6 +56,7 @@ func NewChaincodeSupport(
aclProvider ACLProvider,
processor Processor,
sccp sysccprovider.SystemChaincodeProvider,
platformRegistry *platforms.Registry,
) *ChaincodeSupport {
cs := &ChaincodeSupport{
UserRunsCC: userRunsCC,
Expand All @@ -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,
Expand Down
6 changes: 5 additions & 1 deletion core/chaincode/chaincode_support_test.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand All @@ -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)
}

Expand Down
15 changes: 9 additions & 6 deletions core/chaincode/container_runtime.go
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions core/chaincode/exectransaction_test.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand All @@ -140,14 +143,15 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro
},
),
sccp,
pr,
)
pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport)

// 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)
}

Expand Down Expand Up @@ -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
}
Expand Down
5 changes: 5 additions & 0 deletions core/chaincode/platforms/car/platform.go
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions core/chaincode/platforms/car/vm_helper_test.go
Expand Up @@ -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"
Expand All @@ -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)
}
Expand Down
5 changes: 5 additions & 0 deletions core/chaincode/platforms/golang/platform.go
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions core/chaincode/platforms/java/platform.go
Expand Up @@ -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)
Expand Down
51 changes: 51 additions & 0 deletions core/chaincode/platforms/mock/platform.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions core/chaincode/platforms/node/platform.go
Expand Up @@ -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)
Expand Down
22 changes: 10 additions & 12 deletions core/chaincode/platforms/platforms.go
Expand Up @@ -16,18 +16,15 @@ 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"
)

// 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)
Expand All @@ -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),
}
}
Expand Down
28 changes: 19 additions & 9 deletions core/chaincode/platforms/platforms_test.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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() {
Expand Down
3 changes: 3 additions & 0 deletions core/chaincode/systemchaincode_test.go
Expand Up @@ -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"
Expand Down Expand Up @@ -141,6 +143,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) {
},
),
sccp,
platforms.NewRegistry(&golang.Platform{}),
)
pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport)

Expand Down

0 comments on commit 9112ebf

Please sign in to comment.