Skip to content

Commit 9381acb

Browse files
author
Jason Yellick
committed
[FAB-2253] Track MSP ID per org and make immutable
https://jira.hyperledger.org/browse/FAB-2253 This CR does two things, it tracks the MSP per organization and checks for mutation of the MSP ID. It also exposes access to this MSP ID and the organization name via the configtxapi interfaces. Change-Id: Id8eb219199377beed163fb69e077875d7bb8e1f8 Signed-off-by: Jason Yellick <[email protected]>
1 parent 351f1b8 commit 9381acb

File tree

9 files changed

+133
-66
lines changed

9 files changed

+133
-66
lines changed

common/configtx/api/api.go

+10
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,18 @@ type ChannelConfig interface {
4040
OrdererAddresses() []string
4141
}
4242

43+
type OrgConfig interface {
44+
// Name returns the name this org is referred to in config
45+
Name() string
46+
47+
// MSPID returns the MSP ID associated with this org
48+
MSPID() string
49+
}
50+
4351
// ApplicationOrgConfig stores the per org application config
4452
type ApplicationOrgConfig interface {
53+
OrgConfig
54+
4555
// AnchorPeers returns the list of gossip anchor peers
4656
AnchorPeers() []*pb.AnchorPeer
4757
}

common/configtx/handlers/msp/config.go

+60-24
Original file line numberDiff line numberDiff line change
@@ -20,65 +20,101 @@ import (
2020
"fmt"
2121
"reflect"
2222

23-
"github.com/golang/protobuf/proto"
2423
"github.com/hyperledger/fabric/msp"
25-
"github.com/hyperledger/fabric/protos/common"
2624
mspprotos "github.com/hyperledger/fabric/protos/msp"
2725
)
2826

27+
type pendingMSPConfig struct {
28+
mspConfig *mspprotos.MSPConfig
29+
msp msp.MSP
30+
}
31+
32+
type mspConfigStore struct {
33+
idMap map[string]*pendingMSPConfig
34+
proposedMgr msp.MSPManager
35+
}
36+
2937
// MSPConfigHandler
3038
type MSPConfigHandler struct {
39+
pendingConfig *mspConfigStore
3140
msp.MSPManager
32-
config []*mspprotos.MSPConfig
33-
proposedMgr msp.MSPManager
3441
}
3542

3643
// BeginConfig called when a config proposal is begun
3744
func (bh *MSPConfigHandler) BeginConfig() {
38-
if bh.config != nil || bh.proposedMgr != nil {
45+
if bh.pendingConfig != nil {
3946
panic("Programming error, called BeginConfig while a proposal was in process")
4047
}
41-
bh.config = make([]*mspprotos.MSPConfig, 0)
48+
bh.pendingConfig = &mspConfigStore{
49+
idMap: make(map[string]*pendingMSPConfig),
50+
}
4251
}
4352

4453
// RollbackConfig called when a config proposal is abandoned
4554
func (bh *MSPConfigHandler) RollbackConfig() {
46-
bh.config = nil
47-
bh.proposedMgr = nil
55+
bh.pendingConfig = nil
4856
}
4957

5058
// CommitConfig called when a config proposal is committed
5159
func (bh *MSPConfigHandler) CommitConfig() {
52-
if bh.config == nil {
60+
if bh.pendingConfig == nil {
5361
panic("Programming error, called CommitConfig with no proposal in process")
5462
}
5563

56-
bh.MSPManager = bh.proposedMgr
57-
bh.config = nil
58-
bh.proposedMgr = nil
64+
bh.MSPManager = bh.pendingConfig.proposedMgr
65+
bh.pendingConfig = nil
5966
}
6067

6168
// ProposeConfig called when config is added to a proposal
62-
func (bh *MSPConfigHandler) ProposeConfig(key string, configValue *common.ConfigValue) error {
63-
mspconfig := &mspprotos.MSPConfig{}
64-
err := proto.Unmarshal(configValue.Value, mspconfig)
69+
func (bh *MSPConfigHandler) ProposeMSP(mspConfig *mspprotos.MSPConfig) (msp.MSP, error) {
70+
// check that the type for that MSP is supported
71+
if mspConfig.Type != int32(msp.FABRIC) {
72+
return nil, fmt.Errorf("Setup error: unsupported msp type %d", mspConfig.Type)
73+
}
74+
75+
// create the msp instance
76+
mspInst, err := msp.NewBccspMsp()
6577
if err != nil {
66-
return fmt.Errorf("Error unmarshalling msp config item, err %s", err)
78+
return nil, fmt.Errorf("Creating the MSP manager failed, err %s", err)
6779
}
6880

69-
// TODO handle deduplication more gracefully
70-
for _, oMsp := range bh.config {
71-
if reflect.DeepEqual(oMsp, mspconfig) {
72-
// The MSP is already in the list
73-
return nil
81+
// set it up
82+
err = mspInst.Setup(mspConfig)
83+
if err != nil {
84+
return nil, fmt.Errorf("Setting up the MSP manager failed, err %s", err)
85+
}
86+
87+
// add the MSP to the map of pending MSPs
88+
mspID, err := mspInst.GetIdentifier()
89+
if err != nil {
90+
return nil, fmt.Errorf("Could not extract msp identifier, err %s", err)
91+
}
92+
93+
existingPendingMSPConfig, ok := bh.pendingConfig.idMap[mspID]
94+
if ok && !reflect.DeepEqual(existingPendingMSPConfig.mspConfig, mspConfig) {
95+
return nil, fmt.Errorf("Attempted to define two different versions of MSP: %s", mspID)
96+
} else {
97+
bh.pendingConfig.idMap[mspID] = &pendingMSPConfig{
98+
mspConfig: mspConfig,
99+
msp: mspInst,
74100
}
75101
}
76102

77-
bh.config = append(bh.config, []*mspprotos.MSPConfig{mspconfig}...)
103+
mspList := make([]msp.MSP, len(bh.pendingConfig.idMap))
104+
i := 0
105+
for _, pendingMSP := range bh.pendingConfig.idMap {
106+
mspList[i] = pendingMSP.msp
107+
i++
108+
}
109+
78110
// the only way to make sure that I have a
79111
// workable config is to toss the proposed
80112
// manager, create a new one, call setup on
81113
// it and return whatever error setup gives me
82-
bh.proposedMgr = msp.NewMSPManager()
83-
return bh.proposedMgr.Setup(bh.config)
114+
bh.pendingConfig.proposedMgr = msp.NewMSPManager()
115+
err = bh.pendingConfig.proposedMgr.Setup(mspList)
116+
if err != nil {
117+
return nil, err
118+
}
119+
return mspInst, nil
84120
}

common/configtx/handlers/msp/config_test.go

+4-12
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,21 @@ package msp
1919
import (
2020
"testing"
2121

22-
"github.com/golang/protobuf/proto"
2322
"github.com/hyperledger/fabric/msp"
24-
"github.com/hyperledger/fabric/protos/common"
23+
mspprotos "github.com/hyperledger/fabric/protos/msp"
2524
"github.com/stretchr/testify/assert"
2625
)
2726

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

32-
confBytes, err := proto.Marshal(conf)
33-
assert.NoError(t, err)
34-
35-
ci := &common.ConfigValue{Value: confBytes}
36-
3731
// test success:
3832

3933
// begin/propose/commit
40-
key := "DEFAULT"
41-
4234
mspCH := &MSPConfigHandler{}
4335
mspCH.BeginConfig()
44-
err = mspCH.ProposeConfig(key, ci)
36+
_, err = mspCH.ProposeMSP(conf)
4537
assert.NoError(t, err)
4638
mspCH.CommitConfig()
4739

@@ -55,8 +47,8 @@ func TestMSPConfigManager(t *testing.T) {
5547
// test failure
5648
// begin/propose/commit
5749
mspCH.BeginConfig()
58-
err = mspCH.ProposeConfig(key, ci)
50+
_, err = mspCH.ProposeMSP(conf)
5951
assert.NoError(t, err)
60-
err = mspCH.ProposeConfig(key, &common.ConfigValue{Value: []byte("BARF!")})
52+
_, err = mspCH.ProposeMSP(&mspprotos.MSPConfig{Config: []byte("BARF!")})
6153
assert.Error(t, err)
6254
}

common/configtx/handlers/organization.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import (
2323
mspconfig "github.com/hyperledger/fabric/common/configtx/handlers/msp"
2424
"github.com/hyperledger/fabric/msp"
2525
cb "github.com/hyperledger/fabric/protos/common"
26+
mspprotos "github.com/hyperledger/fabric/protos/msp"
2627

28+
"github.com/golang/protobuf/proto"
2729
"github.com/op/go-logging"
2830
)
2931

@@ -43,6 +45,7 @@ type orgConfig struct {
4345
// In general, it should only be referenced as an Impl for the configtx.Manager
4446
type OrgConfig struct {
4547
id string
48+
mspID string
4649
pendingConfig *orgConfig
4750
config *orgConfig
4851

@@ -88,12 +91,53 @@ func (oc *OrgConfig) CommitConfig() {
8891
oc.pendingConfig = nil
8992
}
9093

94+
// Name returns the name this org is referred to in config
95+
func (oc *OrgConfig) Name() string {
96+
return oc.id
97+
}
98+
99+
// MSPID returns the MSP ID associated with this org
100+
func (oc *OrgConfig) MSPID() string {
101+
return oc.mspID
102+
}
103+
91104
// ProposeConfig is used to add new config to the config proposal
92105
func (oc *OrgConfig) ProposeConfig(key string, configValue *cb.ConfigValue) error {
93106
switch key {
94107
case MSPKey:
95108
logger.Debugf("Initializing org MSP for id %s", oc.id)
96-
return oc.mspConfig.ProposeConfig(key, configValue)
109+
110+
mspconfig := &mspprotos.MSPConfig{}
111+
err := proto.Unmarshal(configValue.Value, mspconfig)
112+
if err != nil {
113+
return fmt.Errorf("Error unmarshalling msp config for org %s, err %s", oc.id, err)
114+
}
115+
116+
logger.Debugf("Setting up MSP")
117+
msp, err := oc.mspConfig.ProposeMSP(mspconfig)
118+
if err != nil {
119+
return err
120+
}
121+
122+
mspID, err := msp.GetIdentifier()
123+
if err != nil {
124+
return fmt.Errorf("Could not extract msp identifier for org %s, err %s", oc.id, err)
125+
}
126+
127+
if mspID == "" {
128+
return fmt.Errorf("MSP for org %s has empty MSP ID", oc.id)
129+
}
130+
131+
// If the mspID has never been initialized, store it to ensure immutability
132+
if oc.mspID == "" {
133+
oc.mspID = mspID
134+
}
135+
136+
if mspID != oc.mspID {
137+
return fmt.Errorf("MSP for org %s attempted to change its identifier from %s to %s", oc.id, oc.mspID, mspID)
138+
}
139+
140+
oc.pendingConfig.msp = msp
97141
default:
98142
logger.Warningf("Uknown org config item with key %s", key)
99143
}

gossip/service/eventer_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ func (ao applicationOrgs) AnchorPeers() []*peer.AnchorPeer {
3232
return ao
3333
}
3434

35+
func (ao applicationOrgs) MSPID() string {
36+
panic("Unimplimented")
37+
}
38+
39+
func (ao applicationOrgs) Name() string {
40+
panic("Unimplimented")
41+
}
42+
3543
type mockReceiver struct {
3644
orgs map[string]configtxapi.ApplicationOrgConfig
3745
sequence uint64

msp/mgmt/testtools/config.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/hyperledger/fabric/common/util"
2424
"github.com/hyperledger/fabric/msp"
2525
"github.com/hyperledger/fabric/msp/mgmt"
26-
mspprotos "github.com/hyperledger/fabric/protos/msp"
2726
)
2827

2928
func getConfigPath(dir string) (string, error) {
@@ -59,9 +58,7 @@ func LoadMSPSetupForTesting(dir string) error {
5958
return err
6059
}
6160

62-
fakeConfig := []*mspprotos.MSPConfig{conf}
63-
64-
err = mgmt.GetManagerForChain(util.GetTestChainID()).Setup(fakeConfig)
61+
err = mgmt.GetManagerForChain(util.GetTestChainID()).Setup([]msp.MSP{mgmt.GetLocalMSP()})
6562
if err != nil {
6663
return err
6764
}

msp/msp.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type MSPManager interface {
5959
IdentityDeserializer
6060

6161
// Setup the MSP manager instance according to configuration information
62-
Setup(msps []*msp.MSPConfig) error
62+
Setup(msps []MSP) error
6363

6464
// GetMSPs Provides a list of Membership Service providers
6565
GetMSPs() (map[string]MSP, error)
@@ -240,7 +240,7 @@ type IdentityIdentifier struct {
240240
// ProviderType indicates the type of an identity provider
241241
type ProviderType int
242242

243-
// The ProviderTYpe of a member relative to the member API
243+
// The ProviderType of a member relative to the member API
244244
const (
245245
FABRIC ProviderType = iota // MSP is of FABRIC type
246246
OTHER // MSP is of OTHER TYPE

msp/msp_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ func TestMain(m *testing.M) {
302302
}
303303

304304
mspMgr = NewMSPManager()
305-
err = mspMgr.Setup([]*msp.MSPConfig{conf})
305+
err = mspMgr.Setup([]MSP{localMsp})
306306
if err != nil {
307307
fmt.Printf("Setup for msp manager should have succeeded, got err %s instead", err)
308308
os.Exit(-1)

msp/mspmgrimpl.go

+2-22
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"fmt"
2121

2222
"github.com/golang/protobuf/proto"
23-
"github.com/hyperledger/fabric/protos/msp"
2423
"github.com/op/go-logging"
2524
)
2625

@@ -42,7 +41,7 @@ func NewMSPManager() MSPManager {
4241
}
4342

4443
// Setup initializes the internal data structures of this manager and creates MSPs
45-
func (mgr *mspManagerImpl) Setup(msps []*msp.MSPConfig) error {
44+
func (mgr *mspManagerImpl) Setup(msps []MSP) error {
4645
if mgr.up {
4746
mspLogger.Infof("MSP manager already up")
4847
return nil
@@ -61,26 +60,7 @@ func (mgr *mspManagerImpl) Setup(msps []*msp.MSPConfig) error {
6160
// create the map that assigns MSP IDs to their manager instance - once
6261
mgr.mspsMap = make(map[string]MSP)
6362

64-
for _, mspConf := range msps {
65-
// check that the type for that MSP is supported
66-
if mspConf.Type != int32(FABRIC) {
67-
return fmt.Errorf("Setup error: unsupported msp type %d", mspConf.Type)
68-
}
69-
70-
mspLogger.Debugf("Setting up MSP")
71-
72-
// create the msp instance
73-
msp, err := NewBccspMsp()
74-
if err != nil {
75-
return fmt.Errorf("Creating the MSP manager failed, err %s", err)
76-
}
77-
78-
// set it up
79-
err = msp.Setup(mspConf)
80-
if err != nil {
81-
return fmt.Errorf("Setting up the MSP manager failed, err %s", err)
82-
}
83-
63+
for _, msp := range msps {
8464
// add the MSP to the map of active MSPs
8565
mspID, err := msp.GetIdentifier()
8666
if err != nil {

0 commit comments

Comments
 (0)