diff --git a/core/chaincode/chaincode_support_test.go b/core/chaincode/chaincode_support_test.go index 0cfa6d21a55..95961512663 100644 --- a/core/chaincode/chaincode_support_test.go +++ b/core/chaincode/chaincode_support_test.go @@ -171,6 +171,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) { config := GlobalConfig() config.StartupTimeout = 10 * time.Second config.ExecuteTimeout = 1 * time.Second + ipRegistry := inproccontroller.NewRegistry() chaincodeSupport := NewChaincodeSupport( config, "0.0.0.0:7052", @@ -182,7 +183,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) { container.NewVMController( map[string]container.VMProvider{ dockercontroller.ContainerType: dockercontroller.NewProvider(), - inproccontroller.ContainerType: inproccontroller.NewProvider(), + inproccontroller.ContainerType: ipRegistry, }, ), ) @@ -192,7 +193,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) { // Mock policy checker policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{}) - scc.RegisterSysCCs() + scc.RegisterSysCCs(ipRegistry) globalBlockNum = make(map[string]uint64, len(chainIDs)) for _, id := range chainIDs { diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 7f634740dc5..a77d29d1b8c 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -119,6 +119,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro certGenerator := accesscontrol.NewAuthenticator(ca) config := GlobalConfig() config.StartupTimeout = 3 * time.Minute + ipRegistry := inproccontroller.NewRegistry() chaincodeSupport := NewChaincodeSupport( config, peerAddress, @@ -130,7 +131,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro container.NewVMController( map[string]container.VMProvider{ dockercontroller.ContainerType: dockercontroller.NewProvider(), - inproccontroller.ContainerType: inproccontroller.NewProvider(), + inproccontroller.ContainerType: ipRegistry, }, ), ) @@ -141,7 +142,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro // Mock policy checker policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{}) - scc.RegisterSysCCs() + scc.RegisterSysCCs(ipRegistry) for _, id := range chainIDs { scc.DeDeploySysCCs(id) diff --git a/core/chaincode/systemchaincode_test.go b/core/chaincode/systemchaincode_test.go index 4366a6060f4..9597a57958c 100644 --- a/core/chaincode/systemchaincode_test.go +++ b/core/chaincode/systemchaincode_test.go @@ -126,6 +126,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) { certGenerator := accesscontrol.NewAuthenticator(ca) config := GlobalConfig() config.ExecuteTimeout = 5 * time.Second + ipRegistry := inproccontroller.NewRegistry() chaincodeSupport := NewChaincodeSupport( config, peerAddress, @@ -137,7 +138,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) { container.NewVMController( map[string]container.VMProvider{ dockercontroller.ContainerType: dockercontroller.NewProvider(), - inproccontroller.ContainerType: inproccontroller.NewProvider(), + inproccontroller.ContainerType: ipRegistry, }, ), ) @@ -161,7 +162,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) { // System chaincode has to be enabled viper.Set("chaincode.system", map[string]string{"sample_syscc": "true"}) - sysccinfo.origSystemCC = scc.MockRegisterSysCCs(sysccs) + sysccinfo.origSystemCC = scc.MockRegisterSysCCs(sysccs, ipRegistry) /////^^^ system initialization completed ^^^ return sysccinfo, lis, chaincodeSupport, nil diff --git a/core/container/inproccontroller/inproccontroller.go b/core/container/inproccontroller/inproccontroller.go index 951294a0aeb..0170e4dd1b2 100644 --- a/core/container/inproccontroller/inproccontroller.go +++ b/core/container/inproccontroller/inproccontroller.go @@ -23,19 +23,6 @@ import ( // is registered with the container.VMController const ContainerType = "SYSTEM" -// Provider implements container.VMProvider -type Provider struct{} - -// NewProvider creates a new instances of Provider -func NewProvider() *Provider { - return &Provider{} -} - -// NewVM creates an inproc VM instance -func (c *Provider) NewVM() container.VM { - return &InprocVM{} -} - type inprocContainer struct { chaincode shim.Chaincode running bool @@ -45,9 +32,10 @@ type inprocContainer struct { } var ( - inprocLogger = flogging.MustGetLogger("inproccontroller") - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) + inprocLogger = flogging.MustGetLogger("inproccontroller") + + // TODO this is a very hacky way to do testing, we should find other ways + // to test, or not statically inject these depenencies. _shimStartInProc = shim.StartInProc _inprocLoggerErrorf = inprocLogger.Errorf ) @@ -61,30 +49,58 @@ func (s SysCCRegisteredErr) Error() string { return fmt.Sprintf("%s already registered", string(s)) } +// Registry stores registered system chaincodes. +// It implements container.VMProvider and scc.Registrar +type Registry struct { + typeRegistry map[string]*inprocContainer + instRegistry map[string]*inprocContainer +} + +// NewRegistry creates an initialized registry, ready to register system chaincodes. +func NewRegistry() *Registry { + return &Registry{ + typeRegistry: make(map[string]*inprocContainer), + instRegistry: make(map[string]*inprocContainer), + } +} + +// NewVM creates an inproc VM instance +func (r *Registry) NewVM() container.VM { + return NewInprocVM(r) +} + //Register registers system chaincode with given path. The deploy should be called to initialize -func Register(path string, cc shim.Chaincode) error { - tmp := typeRegistry[path] +func (r *Registry) Register(path string, cc shim.Chaincode) error { + tmp := r.typeRegistry[path] if tmp != nil { return SysCCRegisteredErr(path) } - typeRegistry[path] = &inprocContainer{chaincode: cc} + r.typeRegistry[path] = &inprocContainer{chaincode: cc} return nil } //InprocVM is a vm. It is identified by a executable name type InprocVM struct { - id string + id string + registry *Registry +} + +// NewInprocVM creates a new InprocVM +func NewInprocVM(r *Registry) *InprocVM { + return &InprocVM{ + registry: r, + } } func (vm *InprocVM) getInstance(ctxt context.Context, ipctemplate *inprocContainer, instName string, args []string, env []string) (*inprocContainer, error) { - ipc := instRegistry[instName] + ipc := vm.registry.instRegistry[instName] if ipc != nil { inprocLogger.Warningf("chaincode instance exists for %s", instName) return ipc, nil } ipc = &inprocContainer{args: args, env: env, chaincode: ipctemplate.chaincode, stopChan: make(chan struct{})} - instRegistry[instName] = ipc + vm.registry.instRegistry[instName] = ipc inprocLogger.Debugf("chaincode instance created for %s", instName) return ipc, nil } @@ -93,7 +109,7 @@ func (vm *InprocVM) getInstance(ctxt context.Context, ipctemplate *inprocContain func (vm *InprocVM) Deploy(ctxt context.Context, ccid ccintf.CCID, args []string, env []string, reader io.Reader) error { path := ccid.ChaincodeSpec.ChaincodeId.Path - ipctemplate := typeRegistry[path] + ipctemplate := vm.registry.typeRegistry[path] if ipctemplate == nil { return fmt.Errorf(fmt.Sprintf("%s not registered. Please register the system chaincode in inprocinstances.go", path)) } @@ -126,7 +142,7 @@ func (ipc *inprocContainer) launchInProc(ctxt context.Context, id string, args [ if env == nil { env = ipc.env } - err := _shimStartInProc(env, args, ipc.chaincode, ccRcvPeerSend, peerRcvCCSend) + err := shim.StartInProc(env, args, ipc.chaincode, ccRcvPeerSend, peerRcvCCSend) if err != nil { err = fmt.Errorf("chaincode-support ended with err: %s", err) _inprocLoggerErrorf("%s", err) @@ -165,7 +181,7 @@ func (ipc *inprocContainer) launchInProc(ctxt context.Context, id string, args [ func (vm *InprocVM) Start(ctxt context.Context, ccid ccintf.CCID, args []string, env []string, filesToUpload map[string][]byte, builder container.Builder) error { path := ccid.ChaincodeSpec.ChaincodeId.Path - ipctemplate := typeRegistry[path] + ipctemplate := vm.registry.typeRegistry[path] if ipctemplate == nil { return fmt.Errorf(fmt.Sprintf("%s not registered", path)) @@ -208,14 +224,14 @@ func (vm *InprocVM) Start(ctxt context.Context, ccid ccintf.CCID, args []string, func (vm *InprocVM) Stop(ctxt context.Context, ccid ccintf.CCID, timeout uint, dontkill bool, dontremove bool) error { path := ccid.ChaincodeSpec.ChaincodeId.Path - ipctemplate := typeRegistry[path] + ipctemplate := vm.registry.typeRegistry[path] if ipctemplate == nil { return fmt.Errorf("%s not registered", path) } instName, _ := vm.GetVMName(ccid, nil) - ipc := instRegistry[instName] + ipc := vm.registry.instRegistry[instName] if ipc == nil { return fmt.Errorf("%s not found", instName) @@ -227,7 +243,7 @@ func (vm *InprocVM) Stop(ctxt context.Context, ccid ccintf.CCID, timeout uint, d ipc.stopChan <- struct{}{} - delete(instRegistry, instName) + delete(vm.registry.instRegistry, instName) //TODO stop return nil } diff --git a/core/container/inproccontroller/inproccontroller_test.go b/core/container/inproccontroller/inproccontroller_test.go index b87fe88c606..27ff15fb2ed 100644 --- a/core/container/inproccontroller/inproccontroller_test.go +++ b/core/container/inproccontroller/inproccontroller_test.go @@ -37,26 +37,19 @@ func TestError(t *testing.T) { } func TestRegisterSuccess(t *testing.T) { - oldTypeRegistry := typeRegistry - defer func() { - typeRegistry = oldTypeRegistry - }() - + r := NewRegistry() shim := MockShim{} - err := Register("path", shim) + err := r.Register("path", shim) assert.Nil(t, err, "err should be nil") - assert.Equal(t, typeRegistry["path"].chaincode, shim, "shim should be correct") + assert.Equal(t, r.typeRegistry["path"].chaincode, shim, "shim should be correct") } func TestRegisterError(t *testing.T) { - oldTypeRegistry := typeRegistry - defer func() { - typeRegistry = oldTypeRegistry - }() - typeRegistry["path"] = &inprocContainer{} + r := NewRegistry() + r.typeRegistry["path"] = &inprocContainer{} shim := MockShim{} - err := Register("path", shim) + err := r.Register("path", shim) assert.NotNil(t, err, "err should not be nil") } @@ -91,52 +84,44 @@ func (c MockContext) Value(key interface{}) interface{} { } func TestGetInstanceChaincodeDoesntExist(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() - mockContext := MockContext{} mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, } - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) args := []string{"a", "b"} env := []string{"a", "b"} container, err := vm.getInstance(mockContext, mockInprocContainer, "instName", args, env) assert.NotNil(t, container, "container should not be nil") assert.Nil(t, err, "err should be nil") - if _, ok := instRegistry["instName"]; !ok { + if _, ok := r.instRegistry["instName"]; !ok { t.Error("correct key hasnt been set on instRegistry") } } func TestGetInstaceChaincodeExists(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() - mockContext := MockContext{} mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, } - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) args := []string{"a", "b"} env := []string{"a", "b"} ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - instRegistry["instName"] = ipc + r.instRegistry["instName"] = ipc container, err := vm.getInstance(mockContext, mockInprocContainer, "instName", args, env) assert.NotNil(t, container, "container should not be nil") assert.Nil(t, err, "err should be nil") - assert.Equal(t, instRegistry["instName"], ipc, "instRegistry[instName] should contain the correct value") + assert.Equal(t, r.instRegistry["instName"], ipc, "instRegistry[instName] should contain the correct value") } type MockReader struct { @@ -147,16 +132,9 @@ func (r MockReader) Read(p []byte) (n int, err error) { } func TestDeployNotRegistered(t *testing.T) { - - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() - mockContext := MockContext{} - vm := InprocVM{ - id: "path", - } + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -174,7 +152,7 @@ func TestDeployNotRegistered(t *testing.T) { env := []string{"a", "b"} mockReader := MockReader{} ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - instRegistry["instName"] = ipc + r.instRegistry["instName"] = ipc err := vm.Deploy(mockContext, ccid, args, env, mockReader) @@ -184,7 +162,8 @@ func TestDeployNotRegistered(t *testing.T) { func TestDeployNoChaincodeInstance(t *testing.T) { mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -202,7 +181,7 @@ func TestDeployNoChaincodeInstance(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := vm.Deploy(mockContext, ccid, args, env, mockReader) assert.NotNil(t, err, "err should not be nil") @@ -210,12 +189,9 @@ func TestDeployNoChaincodeInstance(t *testing.T) { } func TestDeployChaincode(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -235,7 +211,7 @@ func TestDeployChaincode(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := vm.Deploy(mockContext, ccid, args, env, mockReader) assert.Nil(t, err, "err should be nil") @@ -250,8 +226,6 @@ func (ccs MockCCSupport) HandleChaincodeStream(ctx context.Context, stream ccint func TestLaunchInprocCCSupportChan(t *testing.T) { oldShimStartInProc := _shimStartInProc defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) _shimStartInProc = oldShimStartInProc }() @@ -268,9 +242,7 @@ func TestLaunchInprocCCSupportChan(t *testing.T) { args := []string{"a", "b"} env := []string{"a", "b"} - ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - - typeRegistry["path"] = ipc + _ = &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} err := mockInprocContainer.launchInProc(mockContext, "ID", args, env, MockCCSupport{}) assert.Nil(t, err, "err should be nil") @@ -279,8 +251,6 @@ func TestLaunchInprocCCSupportChan(t *testing.T) { func TestLaunchprocNoArgs(t *testing.T) { oldShimStartInProc := _shimStartInProc defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) _shimStartInProc = oldShimStartInProc }() @@ -297,6 +267,7 @@ func TestLaunchprocNoArgs(t *testing.T) { } mockContext := MockContext{} + r := NewRegistry() mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, args: ipcArgs, @@ -304,7 +275,7 @@ func TestLaunchprocNoArgs(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := mockInprocContainer.launchInProc(mockContext, "ID", args, env, MockCCSupport{}) assert.Nil(t, err, "err should be nil") @@ -313,8 +284,6 @@ func TestLaunchprocNoArgs(t *testing.T) { func TestLaunchprocNoEnv(t *testing.T) { oldShimStartInProc := _shimStartInProc defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) _shimStartInProc = oldShimStartInProc }() @@ -331,6 +300,7 @@ func TestLaunchprocNoEnv(t *testing.T) { } mockContext := MockContext{} + r := NewRegistry() mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, env: ipcEnv, @@ -338,7 +308,7 @@ func TestLaunchprocNoEnv(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := mockInprocContainer.launchInProc(mockContext, "ID", args, env, MockCCSupport{}) assert.Nil(t, err, "err should be nil") @@ -348,8 +318,6 @@ func TestLaunchprocShimStartInProcErr(t *testing.T) { oldShimStartInProc := _shimStartInProc oldInprocLoggerErrorf := _inprocLoggerErrorf defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) _shimStartInProc = oldShimStartInProc _inprocLoggerErrorf = oldInprocLoggerErrorf }() @@ -372,13 +340,14 @@ func TestLaunchprocShimStartInProcErr(t *testing.T) { } mockContext := MockContext{} + r := NewRegistry() mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, } ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := mockInprocContainer.launchInProc(mockContext, "ID", args, env, MockCCSupport{}) assert.Nil(t, err, "err should be nil") @@ -394,8 +363,6 @@ func TestLaunchprocCCSupportHandleChaincodeStreamError(t *testing.T) { oldShimStartInProc := _shimStartInProc oldInprocLoggerErrorf := _inprocLoggerErrorf defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) _shimStartInProc = oldShimStartInProc _inprocLoggerErrorf = oldInprocLoggerErrorf }() @@ -411,25 +378,23 @@ func TestLaunchprocCCSupportHandleChaincodeStreamError(t *testing.T) { } mockContext := MockContext{} + r := NewRegistry() mockInprocContainer := &inprocContainer{ chaincode: MockShim{}, } ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := mockInprocContainer.launchInProc(mockContext, "ID", args, env, MockCCSupportErr{}) assert.Nil(t, err, "err should be nil") } func TestStart(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -449,19 +414,16 @@ func TestStart(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: make(chan struct{})} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := vm.Start(mockContext, ccid, args, env, files, nil) assert.Nil(t, err, "err should be nil") } func TestStop(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -484,8 +446,8 @@ func TestStop(t *testing.T) { ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: stopChan} ipc.running = true - typeRegistry["path"] = ipc - instRegistry["name-1"] = ipc + r.typeRegistry["path"] = ipc + r.instRegistry["name-1"] = ipc go func() { err := vm.Stop(mockContext, ccid, 1000, true, true) @@ -497,12 +459,9 @@ func TestStop(t *testing.T) { } func TestStopNoIPCTemplate(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -520,12 +479,9 @@ func TestStopNoIPCTemplate(t *testing.T) { } func TestStopNoIPC(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -547,7 +503,7 @@ func TestStopNoIPC(t *testing.T) { stopChan := make(chan struct{}) ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: stopChan} - typeRegistry["path"] = ipc + r.typeRegistry["path"] = ipc err := vm.Stop(mockContext, ccid, 1000, true, true) assert.NotNil(t, err, "err should not be nil") @@ -555,12 +511,9 @@ func TestStopNoIPC(t *testing.T) { } func TestStopIPCNotRunning(t *testing.T) { - defer func() { - typeRegistry = make(map[string]*inprocContainer) - instRegistry = make(map[string]*inprocContainer) - }() mockContext := MockContext{} - vm := InprocVM{} + r := NewRegistry() + vm := NewInprocVM(r) ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ @@ -582,8 +535,8 @@ func TestStopIPCNotRunning(t *testing.T) { stopChan := make(chan struct{}) ipc := &inprocContainer{args: args, env: env, chaincode: mockInprocContainer.chaincode, stopChan: stopChan} - typeRegistry["path"] = ipc - instRegistry["name-1"] = ipc + r.typeRegistry["path"] = ipc + r.instRegistry["name-1"] = ipc err := vm.Stop(mockContext, ccid, 1000, true, true) assert.NotNil(t, err, "err should not be nil") @@ -591,7 +544,7 @@ func TestStopIPCNotRunning(t *testing.T) { } func TestDestroy(t *testing.T) { - vm := InprocVM{} + vm := NewInprocVM(NewRegistry()) mockContext := MockContext{} ccid := ccintf.CCID{ ChaincodeSpec: &pb.ChaincodeSpec{ diff --git a/core/scc/cscc/configure_test.go b/core/scc/cscc/configure_test.go index 7dcd01a7340..9558ac9712c 100644 --- a/core/scc/cscc/configure_test.go +++ b/core/scc/cscc/configure_test.go @@ -208,7 +208,7 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { aclmgmt.GetACLProvider(), container.NewVMController( map[string]container.VMProvider{ - inproccontroller.ContainerType: inproccontroller.NewProvider(), + inproccontroller.ContainerType: inproccontroller.NewRegistry(), }, ), ) diff --git a/core/scc/importsysccs.go b/core/scc/importsysccs.go index c5b4df6b884..fb9e01862c3 100644 --- a/core/scc/importsysccs.go +++ b/core/scc/importsysccs.go @@ -8,6 +8,7 @@ package scc import ( //import system chaincodes here + "github.com/hyperledger/fabric/core/container/inproccontroller" "github.com/hyperledger/fabric/core/scc/cscc" "github.com/hyperledger/fabric/core/scc/lscc" "github.com/hyperledger/fabric/core/scc/qscc" @@ -105,10 +106,10 @@ func IsSysCCAndNotInvokableCC2CC(name string) bool { // MockRegisterSysCCs is used only for testing // This is needed to break import cycle -func MockRegisterSysCCs(mockSysCCs []*SystemChaincode) []*SystemChaincode { +func MockRegisterSysCCs(mockSysCCs []*SystemChaincode, ipRegistry *inproccontroller.Registry) []*SystemChaincode { orig := systemChaincodes systemChaincodes = mockSysCCs - RegisterSysCCs() + RegisterSysCCs(ipRegistry) return orig } diff --git a/core/scc/register.go b/core/scc/register.go index 73af99ad423..38e1aa03200 100644 --- a/core/scc/register.go +++ b/core/scc/register.go @@ -17,14 +17,14 @@ import ( //note the chaincode must still be deployed and launched like a user chaincode will be // TODO, this is named poorly, it should actually return only the provider, and not do side-effect // initialization for registration. To be tacked in a future CR. -func RegisterSysCCs() sysccprovider.SystemChaincodeProvider { +func RegisterSysCCs(registrar Registrar) sysccprovider.SystemChaincodeProvider { sccp := &ProviderImpl{ Peer: peer.Default, PeerSupport: peer.DefaultSupport, } for _, sysCC := range systemChaincodes { - registerSysCC(sysCC, sccp) + registerSysCC(sysCC, sccp, registrar) } return sccp diff --git a/core/scc/register_pluginsenabled.go b/core/scc/register_pluginsenabled.go index 95eccdf8f1d..9acd658e184 100644 --- a/core/scc/register_pluginsenabled.go +++ b/core/scc/register_pluginsenabled.go @@ -18,7 +18,7 @@ import ( //note the chaincode must still be deployed and launched like a user chaincode will be // TODO, this is named poorly, it should actually return only the provider, and not do side-effect // initialization for registration. To be tacked in a future CR. -func RegisterSysCCs() sysccprovider.SystemChaincodeProvider { +func RegisterSysCCs(registrar Registrar) sysccprovider.SystemChaincodeProvider { systemChaincodes = append(systemChaincodes, loadSysCCs()...) sccp := &ProviderImpl{ @@ -27,7 +27,7 @@ func RegisterSysCCs() sysccprovider.SystemChaincodeProvider { } for _, sysCC := range systemChaincodes { - registerSysCC(sysCC, sccp) + registerSysCC(sysCC, sccp, registrar) } return sccp diff --git a/core/scc/scc_test.go b/core/scc/scc_test.go index f248e0a7dd5..31e21bbe54e 100644 --- a/core/scc/scc_test.go +++ b/core/scc/scc_test.go @@ -14,6 +14,7 @@ import ( "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/sysccprovider" + "github.com/hyperledger/fabric/core/container/inproccontroller" "github.com/hyperledger/fabric/core/ledger/ledgermgmt" ccprovider2 "github.com/hyperledger/fabric/core/mocks/ccprovider" "github.com/hyperledger/fabric/core/peer" @@ -87,28 +88,29 @@ func TestSccProviderImpl_GetQueryExecutorForLedger(t *testing.T) { } func TestMockRegisterAndResetSysCCs(t *testing.T) { - orig := MockRegisterSysCCs([]*SystemChaincode{}) + orig := MockRegisterSysCCs([]*SystemChaincode{}, inproccontroller.NewRegistry()) assert.NotEmpty(t, orig) MockResetSysCCs(orig) assert.Equal(t, len(orig), len(systemChaincodes)) } func TestRegisterSysCC(t *testing.T) { - assert.NotPanics(t, func() { RegisterSysCCs() }, "expected successful init") + assert.NotPanics(t, func() { RegisterSysCCs(inproccontroller.NewRegistry()) }, "expected successful init") + ipRegistry := inproccontroller.NewRegistry() _, err := registerSysCC(&SystemChaincode{ Name: "lscc", Path: "path", Enabled: true, Chaincode: func(sysccprovider.SystemChaincodeProvider) shim.Chaincode { return nil }, - }, nil) + }, nil, ipRegistry) assert.NoError(t, err) _, err = registerSysCC(&SystemChaincode{ Name: "lscc", Path: "path", Enabled: true, Chaincode: func(sysccprovider.SystemChaincodeProvider) shim.Chaincode { return nil }, - }, nil) + }, nil, ipRegistry) assert.Error(t, err) assert.Contains(t, "path already registered", err) } diff --git a/core/scc/sysccapi.go b/core/scc/sysccapi.go index 1e677da9811..d86b069b7de 100644 --- a/core/scc/sysccapi.go +++ b/core/scc/sysccapi.go @@ -27,6 +27,12 @@ import ( var sysccLogger = flogging.MustGetLogger("sccapi") +// Registrar provides a way for system chaincodes to be registered +type Registrar interface { + // Register registers a system chaincode + Register(path string, cc shim.Chaincode) error +} + // SystemChaincode defines the metadata needed to initialize system chaincode // when the fabric comes up. SystemChaincodes are installed by adding an // entry in importsysccs.go @@ -60,13 +66,13 @@ type SystemChaincode struct { } // registerSysCC registers the given system chaincode with the peer -func registerSysCC(syscc *SystemChaincode, sccp sysccprovider.SystemChaincodeProvider) (bool, error) { +func registerSysCC(syscc *SystemChaincode, sccp sysccprovider.SystemChaincodeProvider, registrar Registrar) (bool, error) { if !syscc.Enabled || !isWhitelisted(syscc) { sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s,%t) disabled", syscc.Name, syscc.Path, syscc.Enabled)) return false, nil } - err := inproccontroller.Register(syscc.Path, syscc.Chaincode(sccp)) + err := registrar.Register(syscc.Path, syscc.Chaincode(sccp)) if err != nil { //if the type is registered, the instance may not be... keep going if _, ok := err.(inproccontroller.SysCCRegisteredErr); !ok { diff --git a/peer/node/start.go b/peer/node/start.go index de97784f5d5..8743e22d4ca 100644 --- a/peer/node/start.go +++ b/peer/node/start.go @@ -592,6 +592,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca tlsEnabled := viper.GetBool("peer.tls.enabled") authenticator := accesscontrol.NewAuthenticator(ca) + ipRegistry := inproccontroller.NewRegistry() chaincodeSupport := chaincode.NewChaincodeSupport( chaincode.GlobalConfig(), ccEndpoint, @@ -602,7 +603,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca aclmgmt.GetACLProvider(), container.NewVMController(map[string]container.VMProvider{ dockercontroller.ContainerType: dockercontroller.NewProvider(), - inproccontroller.ContainerType: inproccontroller.NewProvider(), + inproccontroller.ContainerType: ipRegistry, }), ) chaincode.SideEffectInitialize(chaincodeSupport) @@ -613,7 +614,7 @@ func registerChaincodeSupport(grpcServer *comm.GRPCServer, ccEndpoint string, ca } //Now that chaincode is initialized, register all system chaincodes. - sccp := scc.RegisterSysCCs() + sccp := scc.RegisterSysCCs(ipRegistry) chaincodeSupport.SetSysCCProvider(sccp) pb.RegisterChaincodeSupportServer(grpcServer.Server(), ccSrv)