-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-6719] Allow system chaincode plugins
Change-Id: I2db25bdfd8ebffbcb22c3d7374364f6d2d8a6fd6 Signed-off-by: Divyank Katira <[email protected]>
- Loading branch information
Showing
8 changed files
with
227 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// +build experimental | ||
|
||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package scc | ||
|
||
var goBuildTags = "experimental" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// +build !experimental | ||
|
||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package scc | ||
|
||
var goBuildTags = "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package scc | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"plugin" | ||
"sync" | ||
|
||
"github.com/hyperledger/fabric/common/viperutil" | ||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
const ( | ||
sccFactoryMethod = "New" | ||
) | ||
|
||
// PluginConfig SCC plugin configuration | ||
type PluginConfig struct { | ||
Enabled bool `mapstructure:"enabled" yaml:"enabled"` | ||
Name string `mapstructure:"name" yaml:"name"` | ||
Path string `mapstructure:"path" yaml:"path"` | ||
InvokableExternal bool `mapstructure:"invokableExternal" yaml:"invokableExternal"` | ||
InvokableCC2CC bool `mapstructure:"invokableCC2CC" yaml:"invokableCC2CC"` | ||
} | ||
|
||
var once sync.Once | ||
var sccPlugins []*SystemChaincode | ||
|
||
// loadSysCCs reads system chaincode plugin configuration and loads them | ||
func loadSysCCs() []*SystemChaincode { | ||
once.Do(func() { | ||
var config []*PluginConfig | ||
err := viperutil.EnhancedExactUnmarshalKey("chaincode.systemPlugins", &config) | ||
if err != nil { | ||
panic(errors.WithMessage(err, "could not load YAML config")) | ||
} | ||
loadSysCCsWithConfig(config) | ||
}) | ||
return sccPlugins | ||
} | ||
|
||
func loadSysCCsWithConfig(configs []*PluginConfig) { | ||
for _, conf := range configs { | ||
plugin := loadPlugin(conf.Path) | ||
chaincode := &SystemChaincode{ | ||
Enabled: conf.Enabled, | ||
Name: conf.Name, | ||
Path: conf.Path, | ||
Chaincode: *plugin, | ||
InvokableExternal: conf.InvokableExternal, | ||
InvokableCC2CC: conf.InvokableCC2CC, | ||
} | ||
sccPlugins = append(sccPlugins, chaincode) | ||
sysccLogger.Infof("Successfully loaded SCC %s from path %s", chaincode.Name, chaincode.Path) | ||
} | ||
} | ||
|
||
func loadPlugin(path string) *shim.Chaincode { | ||
if _, err := os.Stat(path); err != nil { | ||
panic(fmt.Errorf("Could not find plugin at path %s: %s", path, err)) | ||
} | ||
|
||
p, err := plugin.Open(path) | ||
if err != nil { | ||
panic(fmt.Errorf("Error opening plugin at path %s: %s", path, err)) | ||
} | ||
|
||
sccFactorySymbol, err := p.Lookup(sccFactoryMethod) | ||
if err != nil { | ||
panic(fmt.Errorf( | ||
"Could not find symbol %s. Plugin must export this method", sccFactoryMethod)) | ||
} | ||
|
||
sccFactory, ok := sccFactorySymbol.(func() shim.Chaincode) | ||
if !ok { | ||
panic(fmt.Errorf("Function %s does not match expected definition func() shim.Chaincode", | ||
sccFactoryMethod)) | ||
} | ||
|
||
scc := sccFactory() | ||
|
||
return &scc | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// +build go1.9,linux,cgo | ||
// +build !ppc64le | ||
|
||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package scc | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"testing" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
"github.com/spf13/viper" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
const ( | ||
examplePluginPackage = "github.com/hyperledger/fabric/examples/plugins/scc" | ||
pluginName = "testscc" | ||
) | ||
|
||
var pluginPath = os.TempDir() + "/scc-plugin.so" | ||
|
||
func TestLoadSCCPlugin(t *testing.T) { | ||
buildExamplePlugin(pluginPath, examplePluginPackage) | ||
defer os.Remove(pluginPath) | ||
|
||
testConfig := fmt.Sprintf(` | ||
chaincode: | ||
systemPlugins: | ||
- enabled: true | ||
name: %s | ||
path: %s | ||
invokableExternal: true | ||
invokableCC2CC: true | ||
`, pluginName, pluginPath) | ||
viper.SetConfigType("yaml") | ||
viper.ReadConfig(bytes.NewBuffer([]byte(testConfig))) | ||
|
||
sccs := loadSysCCs() | ||
assert.Len(t, sccs, 1, "expected one SCC to be loaded") | ||
resp := sccs[0].Chaincode.Invoke(nil) | ||
assert.Equal(t, int32(shim.OK), resp.Status, "expected success response from scc") | ||
} | ||
|
||
func TestLoadSCCPluginInvalid(t *testing.T) { | ||
assert.Panics(t, func() { loadPlugin("/invalid/path.so") }, | ||
"expected panic with invalid path") | ||
} | ||
|
||
func buildExamplePlugin(path, pluginPackage string) { | ||
cmd := exec.Command("go", "build", "-tags", goBuildTags, "-o", path, "-buildmode=plugin", | ||
pluginPackage) | ||
output, err := cmd.CombinedOutput() | ||
if err != nil { | ||
panic(fmt.Errorf("Error: %s, Could not build plugin: %s", err, string(output))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
pb "github.com/hyperledger/fabric/protos/peer" | ||
) | ||
|
||
// New returns an implementation of the chaincode interface | ||
func New() shim.Chaincode { | ||
return &scc{} | ||
} | ||
|
||
type scc struct{} | ||
|
||
// Init implements the chaincode shim interface | ||
func (s *scc) Init(stub shim.ChaincodeStubInterface) pb.Response { | ||
return shim.Success(nil) | ||
} | ||
|
||
// Invoke implements the chaincode shim interface | ||
func (s *scc) Invoke(stub shim.ChaincodeStubInterface) pb.Response { | ||
return shim.Success(nil) | ||
} | ||
|
||
func main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters