github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/common/config/msp/config.go (about) 1 /* 2 Copyright IBM Corp. 2017 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 17 package msp 18 19 import ( 20 "fmt" 21 "reflect" 22 "sync" 23 24 "github.com/hyperledger/fabric/msp" 25 mspprotos "github.com/hyperledger/fabric/protos/msp" 26 ) 27 28 type pendingMSPConfig struct { 29 mspConfig *mspprotos.MSPConfig 30 msp msp.MSP 31 } 32 33 type mspConfigStore struct { 34 idMap map[string]*pendingMSPConfig 35 proposedMgr msp.MSPManager 36 } 37 38 // MSPConfigHandler 39 type MSPConfigHandler struct { 40 pendingConfig map[interface{}]*mspConfigStore 41 pendingLock sync.RWMutex 42 msp.MSPManager 43 } 44 45 func NewMSPConfigHandler() *MSPConfigHandler { 46 return &MSPConfigHandler{ 47 pendingConfig: make(map[interface{}]*mspConfigStore), 48 } 49 } 50 51 // BeginConfig called when a config proposal is begun 52 func (bh *MSPConfigHandler) BeginConfig(tx interface{}) { 53 bh.pendingLock.Lock() 54 defer bh.pendingLock.Unlock() 55 _, ok := bh.pendingConfig[tx] 56 if ok { 57 panic("Programming error, called BeginConfig mulitply for the same tx") 58 } 59 bh.pendingConfig[tx] = &mspConfigStore{ 60 idMap: make(map[string]*pendingMSPConfig), 61 } 62 } 63 64 // RollbackProposals called when a config proposal is abandoned 65 func (bh *MSPConfigHandler) RollbackProposals(tx interface{}) { 66 bh.pendingLock.Lock() 67 defer bh.pendingLock.Unlock() 68 delete(bh.pendingConfig, tx) 69 } 70 71 // CommitProposals called when a config proposal is committed 72 func (bh *MSPConfigHandler) CommitProposals(tx interface{}) { 73 bh.pendingLock.Lock() 74 defer bh.pendingLock.Unlock() 75 pendingConfig, ok := bh.pendingConfig[tx] 76 if !ok { 77 panic("Programming error, called BeginConfig mulitply for the same tx") 78 } 79 80 bh.MSPManager = pendingConfig.proposedMgr 81 delete(bh.pendingConfig, tx) 82 } 83 84 // ProposeValue called when config is added to a proposal 85 func (bh *MSPConfigHandler) ProposeMSP(tx interface{}, mspConfig *mspprotos.MSPConfig) (msp.MSP, error) { 86 bh.pendingLock.RLock() 87 pendingConfig, ok := bh.pendingConfig[tx] 88 bh.pendingLock.RUnlock() 89 if !ok { 90 panic("Programming error, called BeginConfig mulitply for the same tx") 91 } 92 93 // check that the type for that MSP is supported 94 if mspConfig.Type != int32(msp.FABRIC) { 95 return nil, fmt.Errorf("Setup error: unsupported msp type %d", mspConfig.Type) 96 } 97 98 // create the msp instance 99 mspInst, err := msp.NewBccspMsp() 100 if err != nil { 101 return nil, fmt.Errorf("Creating the MSP manager failed, err %s", err) 102 } 103 104 // set it up 105 err = mspInst.Setup(mspConfig) 106 if err != nil { 107 return nil, fmt.Errorf("Setting up the MSP manager failed, err %s", err) 108 } 109 110 // add the MSP to the map of pending MSPs 111 mspID, err := mspInst.GetIdentifier() 112 if err != nil { 113 return nil, fmt.Errorf("Could not extract msp identifier, err %s", err) 114 } 115 116 existingPendingMSPConfig, ok := pendingConfig.idMap[mspID] 117 if ok && !reflect.DeepEqual(existingPendingMSPConfig.mspConfig, mspConfig) { 118 return nil, fmt.Errorf("Attempted to define two different versions of MSP: %s", mspID) 119 } 120 121 pendingConfig.idMap[mspID] = &pendingMSPConfig{ 122 mspConfig: mspConfig, 123 msp: mspInst, 124 } 125 126 return mspInst, nil 127 } 128 129 // PreCommit instantiates the MSP manager 130 func (bh *MSPConfigHandler) PreCommit(tx interface{}) error { 131 bh.pendingLock.RLock() 132 pendingConfig, ok := bh.pendingConfig[tx] 133 bh.pendingLock.RUnlock() 134 if !ok { 135 panic("Programming error, called PreCommit for tx which was not started") 136 } 137 138 if len(pendingConfig.idMap) == 0 { 139 // Cannot instantiate an MSP manager with no MSPs 140 return nil 141 } 142 143 mspList := make([]msp.MSP, len(pendingConfig.idMap)) 144 i := 0 145 for _, pendingMSP := range pendingConfig.idMap { 146 mspList[i] = pendingMSP.msp 147 i++ 148 } 149 150 pendingConfig.proposedMgr = msp.NewMSPManager() 151 err := pendingConfig.proposedMgr.Setup(mspList) 152 return err 153 }