Skip to content

Commit

Permalink
[FAB-1647] Yaml used to configure BCCSP
Browse files Browse the repository at this point in the history
This time use Yaml files in peer and orderer to configure BCCSP
factory

The main three changes are for the two executables:
- peer
- orderer
- chaincode shim

They each have their own config yaml file, added a BCCSP section.
The BCCSP is paired with the MSP configuration directory. The
SW BCCSP Filestore takes over the keystore directory.

Where it gets complicated are all the tests. The tests working
against MSP were easy to fix (circa patch set 8)

Patch set https://gerrit.hyperledger.org/r/#/c/6235/4 introduced
more uses of BCCSP. Configuring those mostly to SW/nil, except
need to find an appropriate location for InitFactories(nil). Either:
- many/most test cases have function called SetupTestConfig()
- TestMain() otherwise

Since the TestMain() updates were getting unmanageable and
unscalable (everyone writting unit tests would now need to know
about InitFactories()), added a concept of bootBCCSP to
bccsp/factory.

bootBCCSP is meant to be used by test cases that only need keyless
crypto operations (i.e. SHA) or where keeping keys does not matter.

Change-Id: I084d7927550e7fad7a25cf2062dc20220cf81ccd
Signed-off-by: Volodymyr Paprotski <vpaprots@ca.ibm.com>
  • Loading branch information
Volodymyr Paprotski committed Feb 22, 2017
1 parent 7c1934a commit 3ee0333
Show file tree
Hide file tree
Showing 29 changed files with 236 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ K := $(foreach exec,$(EXECUTABLES),\
GOSHIM_DEPS = $(shell ./scripts/goListFiles.sh $(PKGNAME)/core/chaincode/shim)
JAVASHIM_DEPS = $(shell git ls-files core/chaincode/shim/java)
PROTOS = $(shell git ls-files *.proto | grep -v vendor)
MSP_SAMPLECONFIG = $(shell git ls-files msp/sampleconfig/*.pem)
MSP_SAMPLECONFIG = $(shell git ls-files msp/sampleconfig/*)
PROJECT_FILES = $(shell git ls-files)
IMAGES = peer orderer ccenv javaenv buildenv testenv zookeeper kafka couchdb

Expand Down
16 changes: 15 additions & 1 deletion bccsp/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ var (
// Default BCCSP
defaultBCCSP bccsp.BCCSP

// when InitFactories has not been called yet (should only happen
// in test cases), use this BCCSP temporarily
bootBCCSP bccsp.BCCSP

// BCCSP Factories
bccspMap map[string]bccsp.BCCSP

// factories' Sync on Initialization
factoriesInitOnce sync.Once
bootBCCSPInitOnce sync.Once

// Factories' Initialization Error
factoriesInitError error
Expand All @@ -53,7 +58,16 @@ type BCCSPFactory interface {
// GetDefault returns a non-ephemeral (long-term) BCCSP
func GetDefault() bccsp.BCCSP {
if defaultBCCSP == nil {
panic("BCCSP Factory: Must call InitFactories before using BCCSP!")
logger.Warning("Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.")
bootBCCSPInitOnce.Do(func() {
var err error
f := &SWFactory{}
bootBCCSP, err = f.Get(&DefaultOpts)
if err != nil {
panic("BCCSP Internal error, failed initialization with DefaultOpts!")
}
})
return bootBCCSP
}
return defaultBCCSP
}
Expand Down
3 changes: 0 additions & 3 deletions bccsp/factory/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ var DefaultOpts = FactoryOpts{
},
}

// FIXME! FIXME! This needs to be moved to where viper reads in configs!
var myHack = InitFactories(nil)

// FactoryName returns the name of the provider
func (o *FactoryOpts) FactoryName() string {
return o.ProviderName
Expand Down
4 changes: 2 additions & 2 deletions common/configtx/test/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const sampleOrgID = "DEFAULT"

// ApplicationOrgTemplate returns the SAMPLE org with MSP template
func ApplicationOrgTemplate() configtx.Template {
mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, nil, sampleOrgID)
if err != nil {
logger.Panicf("Could not load sample MSP config: %s", err)
}
Expand All @@ -100,7 +100,7 @@ func ApplicationOrgTemplate() configtx.Template {

// OrdererOrgTemplate returns the SAMPLE org with MSP template
func OrdererOrgTemplate() configtx.Template {
mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, nil, sampleOrgID)
if err != nil {
logger.Panicf("Could not load sample MSP config: %s", err)
}
Expand Down
12 changes: 12 additions & 0 deletions common/configtx/tool/configtx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ Organizations:
# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: msp/sampleconfig

# BCCSP (Blockchain crypto provider): Select which crypto implementation or
# library to use
BCCSP:
Default: SW
SW:
Hash: SHA3
Security: 256
# Location of Key Store. If this is unset, a location will
# be chosen using 'MSPDir'/keystore
FileKeyStore:
KeyStore:

AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
Expand Down
3 changes: 3 additions & 0 deletions common/configtx/tool/localconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

bccsp "github.com/hyperledger/fabric/bccsp/factory"
)

const (
Expand Down Expand Up @@ -65,6 +67,7 @@ type Organization struct {
Name string
ID string
MSPDir string
BCCSP *bccsp.FactoryOpts

// Note, the viper deserialization does not seem to care for
// embedding of types, so we use one organization structure for
Expand Down
4 changes: 2 additions & 2 deletions common/configtx/tool/provisional/provisional.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func New(conf *genesisconfig.Profile) Generator {
}

for _, org := range conf.Orderer.Organizations {
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID)
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.BCCSP, org.ID)
if err != nil {
logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err)
}
Expand Down Expand Up @@ -143,7 +143,7 @@ func New(conf *genesisconfig.Profile) Generator {
policies.TemplateImplicitMetaMajorityPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.AdminsPolicyKey),
}
for _, org := range conf.Application.Organizations {
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.ID)
mspConfig, err := msp.GetLocalMspConfig(org.MSPDir, org.BCCSP, org.ID)
if err != nil {
logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err)
}
Expand Down
2 changes: 1 addition & 1 deletion common/configvalues/msp/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
)

func TestMSPConfigManager(t *testing.T) {
conf, err := msp.GetLocalMspConfig("../../../msp/sampleconfig/", "DEFAULT")
conf, err := msp.GetLocalMspConfig("../../../msp/sampleconfig/", nil, "DEFAULT")
assert.NoError(t, err)

// test success:
Expand Down
2 changes: 1 addition & 1 deletion common/localmsp/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestMain(m *testing.M) {
mspMgrConfigDir = os.Getenv("GOPATH") + "/src/github.com/hyperledger/fabric/msp/sampleconfig/"
}

if err := mspmgmt.LoadLocalMsp(mspMgrConfigDir, "DEFAULT"); err != nil {
if err := mspmgmt.LoadLocalMsp(mspMgrConfigDir, nil, "DEFAULT"); err != nil {
os.Exit(-1)
}

Expand Down
8 changes: 8 additions & 0 deletions core/chaincode/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

"github.com/hyperledger/fabric/bccsp/factory"
)

// Config the config wrapper structure
Expand Down Expand Up @@ -71,4 +73,10 @@ func SetupTestConfig() {
// Set the number of maxprocs
var numProcsDesired = viper.GetInt("peer.gomaxprocs")
chaincodeLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2))

// Init the BCCSP
err = factory.InitFactories(nil)
if err != nil {
panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err))
}
}
6 changes: 6 additions & 0 deletions core/chaincode/shim/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/core/comm"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
Expand Down Expand Up @@ -76,6 +77,11 @@ func Start(cc Chaincode) error {

SetChaincodeLoggingLevel()

err := factory.InitFactories(&factory.DefaultOpts)
if err != nil {
return fmt.Errorf("Internal error, BCCSP could not be initialized with default options: %s", err)
}

flag.StringVar(&peerAddress, "peer.address", "", "peer address")

flag.Parse()
Expand Down
16 changes: 16 additions & 0 deletions core/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/msp"
)

// Config the config wrapper structure
Expand Down Expand Up @@ -74,4 +77,17 @@ func SetupTestConfig(pathToOpenchainYaml string) {
var numProcsDesired = viper.GetInt("peer.gomaxprocs")
configLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2))

// Init the BCCSP
var bccspConfig *factory.FactoryOpts
err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig)
if err != nil {
bccspConfig = nil
}

msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore")

err = factory.InitFactories(bccspConfig)
if err != nil {
panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err))
}
}
16 changes: 16 additions & 0 deletions core/container/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/msp"
)

// Config the config wrapper structure
Expand Down Expand Up @@ -73,4 +76,17 @@ func SetupTestConfig() {
var numProcsDesired = viper.GetInt("peer.gomaxprocs")
vmLogger.Debugf("setting Number of procs to %d, was %d\n", numProcsDesired, runtime.GOMAXPROCS(2))

// Init the BCCSP
var bccspConfig *factory.FactoryOpts
err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig)
if err != nil {
bccspConfig = nil
}

msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore")

err = factory.InitFactories(bccspConfig)
if err != nil {
panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err))
}
}
17 changes: 17 additions & 0 deletions core/endorser/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/msp"
)

// Config the config wrapper structure
Expand Down Expand Up @@ -68,4 +71,18 @@ func SetupTestConfig() {

// Set the number of maxprocs
viper.GetInt("peer.gomaxprocs")

// Init the BCCSP
var bccspConfig *factory.FactoryOpts
err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig)
if err != nil {
bccspConfig = nil
}

msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore")

err = factory.InitFactories(bccspConfig)
if err != nil {
panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err))
}
}
10 changes: 10 additions & 0 deletions core/endorser/endorser_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,16 @@ peer:
enabled: false
listenAddress: 0.0.0.0:6060

# BCCSP (Blockchain crypto provider): Select which crypto implementation or
# library to use
BCCSP:
Default: SW
SW:
Hash: SHA3
Security: 256
FileKeyStore:
KeyStore:

###############################################################################
#
# VM section
Expand Down
17 changes: 17 additions & 0 deletions events/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (

"github.com/op/go-logging"
"github.com/spf13/viper"

"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/msp"
)

// Config the config wrapper structure
Expand Down Expand Up @@ -64,4 +67,18 @@ func SetupTestConfig() {
}

SetupTestLogging()

// Init the BCCSP
var bccspConfig *factory.FactoryOpts
err = viper.UnmarshalKey("peer.BCCSP", &bccspConfig)
if err != nil {
bccspConfig = nil
}

msp.SetupBCCSPKeystoreConfig(bccspConfig, viper.GetString("peer.mspConfigPath")+"/keystore")

err = factory.InitFactories(bccspConfig)
if err != nil {
panic(fmt.Errorf("Could not initialize BCCSP Factories [%s]", err))
}
}
47 changes: 34 additions & 13 deletions msp/configbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"encoding/pem"
"path/filepath"

"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/protos/msp"
)

Expand Down Expand Up @@ -87,13 +88,39 @@ const (
intermediatecerts = "intermediatecerts"
)

func GetLocalMspConfig(dir string, ID string) (*msp.MSPConfig, error) {
func SetupBCCSPKeystoreConfig(bccspConfig *factory.FactoryOpts, keystoreDir string) {
if bccspConfig == nil {
bccspConfig = &factory.DefaultOpts
}

if bccspConfig.ProviderName == "SW" {
if bccspConfig.SwOpts == nil {
bccspConfig.SwOpts = factory.DefaultOpts.SwOpts
}

// Only override the KeyStorePath if it was left empty
if bccspConfig.SwOpts.FileKeystore == nil ||
bccspConfig.SwOpts.FileKeystore.KeyStorePath == "" {
bccspConfig.SwOpts.Ephemeral = false
bccspConfig.SwOpts.FileKeystore = &factory.FileKeystoreOpts{KeyStorePath: keystoreDir}
}
}
}

func GetLocalMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string) (*msp.MSPConfig, error) {
cacertDir := filepath.Join(dir, cacerts)
signcertDir := filepath.Join(dir, signcerts)
admincertDir := filepath.Join(dir, admincerts)
keystoreDir := filepath.Join(dir, keystore)
intermediatecertsDir := filepath.Join(dir, intermediatecerts)

SetupBCCSPKeystoreConfig(bccspConfig, keystoreDir)

err := factory.InitFactories(bccspConfig)
if err != nil {
return nil, fmt.Errorf("Could not initialize BCCSP Factories [%s]", err)
}

cacerts, err := getPemMaterialFromDir(cacertDir)
if err != nil || len(cacerts) == 0 {
return nil, fmt.Errorf("Could not load a valid ca certificate from directory %s, err %s", cacertDir, err)
Expand All @@ -109,22 +136,16 @@ func GetLocalMspConfig(dir string, ID string) (*msp.MSPConfig, error) {
return nil, fmt.Errorf("Could not load a valid admin certificate from directory %s, err %s", admincertDir, err)
}

keys, err := getPemMaterialFromDir(keystoreDir)
if err != nil || len(keys) == 0 {
return nil, fmt.Errorf("Could not load a valid signing key from directory %s, err %s", keystoreDir, err)
}

intermediatecert, _ := getPemMaterialFromDir(intermediatecertsDir)
// intermediate certs are not mandatory

// FIXME: for now we're making the following assumptions
// 1) there is exactly one signing cert
// 2) there is exactly one signing key
// 3) the cert and the key match

keyinfo := &msp.KeyInfo{KeyIdentifier: "PEER", KeyMaterial: keys[0]}
/* FIXME: for now we're making the following assumptions
1) there is exactly one signing cert
2) BCCSP's KeyStore has the the private key that matches SKI of
signing cert
*/

sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: keyinfo}
sigid := &msp.SigningIdentityInfo{PublicSigner: signcert[0], PrivateSigner: nil}

fmspconf := &msp.FabricMSPConfig{
Admins: admincert,
Expand Down
Loading

1 comment on commit 3ee0333

@ikichigai
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great!

Please sign in to comment.