Skip to content

Commit 8ba61a9

Browse files
committed
BCCSP Factory support
This change-set introduces support for multiple BCCSP factories. This way, it will be possible to have software-based as well as hardware-based BCCSP implementations. The fatory provides also access to a default BCCSP that represents the BCCSP to be used by default as it is configured via viper. Tests have been added to test the factories. This change-set comes in the context of: https://jira.hyperledger.org/browse/FAB-354 Change-Id: Ib83f1fc31fa0ac77daa76f97684563e4c6e53877 Signed-off-by: Angelo De Caro <[email protected]>
1 parent b3bd3fa commit 8ba61a9

File tree

4 files changed

+298
-0
lines changed

4 files changed

+298
-0
lines changed

core/crypto/bccsp/factory/factory.go

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package factory
17+
18+
import (
19+
"errors"
20+
"fmt"
21+
"sync"
22+
23+
"github.com/hyperledger/fabric/core/crypto/bccsp"
24+
"github.com/spf13/viper"
25+
)
26+
27+
var (
28+
// Default BCCSP
29+
defaultBCCSP bccsp.BCCSP
30+
31+
// BCCSP Factories
32+
factories map[string]BCCSPFactory
33+
34+
// factories' Sync on Initialization
35+
factoriesInitOnce sync.Once
36+
37+
// Factories' Initialization Error
38+
factoriesInitError error
39+
)
40+
41+
// BCCSPFactory is used to get instances of the BCCSP interface.
42+
// A Factory has name used to address it.
43+
type BCCSPFactory interface {
44+
45+
// Name returns the name of this factory
46+
Name() string
47+
48+
// Get returns an instance of BCCSP using opts.
49+
Get(opts Opts) (bccsp.BCCSP, error)
50+
}
51+
52+
// Opts contains options for instantiating BCCSPs.
53+
type Opts interface {
54+
55+
// FactoryName returns the name of the factory to be used
56+
FactoryName() string
57+
58+
// Ephemeral returns true if the BCCSP has to be ephemeral, false otherwise
59+
Ephemeral() bool
60+
}
61+
62+
// GetDefault returns a non-ephemeral (long-term) BCCSP
63+
func GetDefault() (bccsp.BCCSP, error) {
64+
if err := initFactories(); err != nil {
65+
return nil, err
66+
}
67+
68+
return defaultBCCSP, nil
69+
}
70+
71+
// GetBCCSP returns a BCCSP created according to the options passed in input.
72+
func GetBCCSP(opts Opts) (bccsp.BCCSP, error) {
73+
if err := initFactories(); err != nil {
74+
return nil, err
75+
}
76+
77+
return getBCCSPInternal(opts)
78+
}
79+
80+
func initFactories() error {
81+
factoriesInitOnce.Do(func() {
82+
// Initialize factories map
83+
if factoriesInitError = initFactoriesMap(); factoriesInitError != nil {
84+
return
85+
}
86+
87+
// Create default non-ephemeral (long-term) BCCSP
88+
defaultBCCSP, factoriesInitError = createDefaultBCCSP()
89+
if factoriesInitError != nil {
90+
return
91+
}
92+
})
93+
return factoriesInitError
94+
}
95+
96+
func initFactoriesMap() error {
97+
factories = make(map[string]BCCSPFactory)
98+
99+
// Software-Based BCCSP
100+
f := &SWFactory{}
101+
factories[f.Name()] = f
102+
103+
return nil
104+
}
105+
106+
func createDefaultBCCSP() (bccsp.BCCSP, error) {
107+
defaultBCCSPFactoryName := viper.GetString("bccsp.default")
108+
if defaultBCCSPFactoryName == "" {
109+
defaultBCCSPFactoryName = SoftwareBasedFactoryName
110+
}
111+
112+
return getBCCSPInternal(&DefaultOpts{defaultBCCSPFactoryName, false})
113+
}
114+
115+
func getBCCSPInternal(opts Opts) (bccsp.BCCSP, error) {
116+
// Validate arguments
117+
if opts == nil {
118+
return nil, errors.New("Cannot instantiate a factory with 'nil' Opts. A fully instantiated BCCSP Opts struct must be provided.")
119+
}
120+
121+
f, ok := factories[opts.FactoryName()]
122+
if ok {
123+
return f.Get(opts)
124+
}
125+
126+
return nil, fmt.Errorf("Factory [%s] does not exist.", opts.FactoryName())
127+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package factory
17+
18+
// DefaultOpts offers a default implementation for Opts
19+
type DefaultOpts struct {
20+
ProviderName string
21+
EphemeralFlag bool
22+
}
23+
24+
// FactoryName returns the name of the provider
25+
func (o *DefaultOpts) FactoryName() string {
26+
return o.ProviderName
27+
}
28+
29+
// Ephemeral returns true if the CSP has to be ephemeral, false otherwise
30+
func (o *DefaultOpts) Ephemeral() bool {
31+
return o.EphemeralFlag
32+
}
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package factory
17+
18+
import "testing"
19+
20+
func TestGetDefault(t *testing.T) {
21+
bccsp, err := GetDefault()
22+
if err != nil {
23+
t.Fatalf("Failed getting default BCCSP [%s]", err)
24+
}
25+
if bccsp == nil {
26+
t.Fatal("Failed getting default BCCSP. Nil instance.")
27+
}
28+
}
29+
30+
func TestGetBCCPEphemeral(t *testing.T) {
31+
bccsp1, err := GetBCCSP(&SwOpts{EphemeralFlag: true})
32+
if err != nil {
33+
t.Fatalf("Failed getting ephemeral software-based BCCSP [%s]", err)
34+
}
35+
36+
bccsp2, err := GetBCCSP(&SwOpts{EphemeralFlag: true})
37+
if err != nil {
38+
t.Fatalf("Failed getting ephemeral software-based BCCSP [%s]", err)
39+
}
40+
41+
if bccsp1 == bccsp2 {
42+
t.Fatal("Ephemeral BCCSPs should point to different instances")
43+
}
44+
}
45+
46+
func TestGetBCCP2Ephemeral(t *testing.T) {
47+
bccsp1, err := GetBCCSP(&SwOpts{EphemeralFlag: false})
48+
if err != nil {
49+
t.Fatalf("Failed getting non-ephemeral software-based BCCSP [%s]", err)
50+
}
51+
52+
bccsp2, err := GetBCCSP(&SwOpts{EphemeralFlag: false})
53+
if err != nil {
54+
t.Fatalf("Failed getting non-ephemeral software-based BCCSP [%s]", err)
55+
}
56+
57+
if bccsp1 != bccsp2 {
58+
t.Fatal("Non-ephemeral BCCSPs should point to the same instance")
59+
}
60+
}
+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package factory
17+
18+
import (
19+
"errors"
20+
"fmt"
21+
"sync"
22+
23+
"github.com/hyperledger/fabric/core/crypto/bccsp"
24+
"github.com/hyperledger/fabric/core/crypto/bccsp/sw"
25+
)
26+
27+
const (
28+
// SoftwareBasedFactoryName is the name of the factory of the software-based BCCSP implementation
29+
SoftwareBasedFactoryName = "SW"
30+
)
31+
32+
// SWFactory is the factory of the software-based BCCSP.
33+
type SWFactory struct {
34+
initOnce sync.Once
35+
bccsp bccsp.BCCSP
36+
err error
37+
}
38+
39+
// Name returns the name of this factory
40+
func (f *SWFactory) Name() string {
41+
return SoftwareBasedFactoryName
42+
}
43+
44+
// Get returns an instance of BCCSP using Opts.
45+
func (f *SWFactory) Get(opts Opts) (bccsp.BCCSP, error) {
46+
// Validate arguments
47+
if opts == nil {
48+
return nil, errors.New("Invalid opts. It must not be nil.")
49+
}
50+
51+
if opts.FactoryName() != f.Name() {
52+
return nil, fmt.Errorf("Invalid Provider Name [%s]. Opts must refer to [%s].", opts.FactoryName(), f.Name())
53+
}
54+
55+
if !opts.Ephemeral() {
56+
f.initOnce.Do(func() {
57+
f.bccsp, f.err = sw.New()
58+
return
59+
})
60+
return f.bccsp, f.err
61+
}
62+
63+
return sw.New()
64+
}
65+
66+
// SwOpts contains options for the SWFactory
67+
type SwOpts struct {
68+
EphemeralFlag bool
69+
}
70+
71+
// FactoryName returns the name of the provider
72+
func (o *SwOpts) FactoryName() string {
73+
return SoftwareBasedFactoryName
74+
}
75+
76+
// Ephemeral returns true if the CSP has to be ephemeral, false otherwise
77+
func (o *SwOpts) Ephemeral() bool {
78+
return o.EphemeralFlag
79+
}

0 commit comments

Comments
 (0)