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  }