github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/multichain/manager.go (about)

     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  
    17  package multichain
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/hyperledger/fabric/common/configtx"
    23  	configtxapi "github.com/hyperledger/fabric/common/configtx/api"
    24  	configvaluesapi "github.com/hyperledger/fabric/common/configvalues"
    25  	ordererledger "github.com/hyperledger/fabric/orderer/ledger"
    26  	cb "github.com/hyperledger/fabric/protos/common"
    27  	"github.com/hyperledger/fabric/protos/utils"
    28  	"github.com/op/go-logging"
    29  
    30  	"github.com/golang/protobuf/proto"
    31  	"github.com/hyperledger/fabric/common/crypto"
    32  )
    33  
    34  var logger = logging.MustGetLogger("orderer/multichain")
    35  
    36  // Manager coordinates the creation and access of chains
    37  type Manager interface {
    38  	// GetChain retrieves the chain support for a chain (and whether it exists)
    39  	GetChain(chainID string) (ChainSupport, bool)
    40  
    41  	// SystemChannelID returns the channel ID for the system channel
    42  	SystemChannelID() string
    43  }
    44  
    45  type configResources struct {
    46  	configtxapi.Manager
    47  }
    48  
    49  func (cr *configResources) SharedConfig() configvaluesapi.Orderer {
    50  	return cr.OrdererConfig()
    51  }
    52  
    53  type ledgerResources struct {
    54  	*configResources
    55  	ledger ordererledger.ReadWriter
    56  }
    57  
    58  type multiLedger struct {
    59  	chains          map[string]*chainSupport
    60  	consenters      map[string]Consenter
    61  	ledgerFactory   ordererledger.Factory
    62  	signer          crypto.LocalSigner
    63  	systemChannelID string
    64  }
    65  
    66  func getConfigTx(reader ordererledger.Reader) *cb.Envelope {
    67  	lastBlock := ordererledger.GetBlock(reader, reader.Height()-1)
    68  	index, err := utils.GetLastConfigIndexFromBlock(lastBlock)
    69  	if err != nil {
    70  		logger.Panicf("Chain did not have appropriately encoded last config in its latest block: %s", err)
    71  	}
    72  	configBlock := ordererledger.GetBlock(reader, index)
    73  	if configBlock == nil {
    74  		logger.Panicf("Config block does not exist")
    75  	}
    76  
    77  	return utils.ExtractEnvelopeOrPanic(configBlock, 0)
    78  }
    79  
    80  // NewManagerImpl produces an instance of a Manager
    81  func NewManagerImpl(ledgerFactory ordererledger.Factory, consenters map[string]Consenter, signer crypto.LocalSigner) Manager {
    82  	ml := &multiLedger{
    83  		chains:        make(map[string]*chainSupport),
    84  		ledgerFactory: ledgerFactory,
    85  		consenters:    consenters,
    86  		signer:        signer,
    87  	}
    88  
    89  	existingChains := ledgerFactory.ChainIDs()
    90  	for _, chainID := range existingChains {
    91  		rl, err := ledgerFactory.GetOrCreate(chainID)
    92  		if err != nil {
    93  			logger.Fatalf("Ledger factory reported chainID %s but could not retrieve it: %s", chainID, err)
    94  		}
    95  		configTx := getConfigTx(rl)
    96  		if configTx == nil {
    97  			logger.Fatalf("Could not find config transaction for chain %s", chainID)
    98  		}
    99  		ledgerResources := ml.newLedgerResources(configTx)
   100  		chainID := ledgerResources.ChainID()
   101  
   102  		if ledgerResources.SharedConfig().ChainCreationPolicyNames() != nil {
   103  			if ml.systemChannelID != "" {
   104  				logger.Fatalf("There appear to be two system chains %s and %s", ml.systemChannelID, chainID)
   105  			}
   106  			chain := newChainSupport(createSystemChainFilters(ml, ledgerResources),
   107  				ledgerResources,
   108  				consenters,
   109  				signer)
   110  			logger.Infof("Starting with system channel: %s and orderer type %s", chainID, chain.SharedConfig().ConsensusType())
   111  			ml.chains[string(chainID)] = chain
   112  			ml.systemChannelID = chainID
   113  			// We delay starting this chain, as it might try to copy and replace the chains map via newChain before the map is fully built
   114  			defer chain.start()
   115  		} else {
   116  			logger.Debugf("Starting chain: %x", chainID)
   117  			chain := newChainSupport(createStandardFilters(ledgerResources),
   118  				ledgerResources,
   119  				consenters,
   120  				signer)
   121  			ml.chains[string(chainID)] = chain
   122  			chain.start()
   123  		}
   124  
   125  	}
   126  
   127  	if ml.systemChannelID == "" {
   128  		logger.Panicf("No system chain found")
   129  	}
   130  
   131  	return ml
   132  }
   133  
   134  func (ml *multiLedger) SystemChannelID() string {
   135  	return ml.systemChannelID
   136  }
   137  
   138  // GetChain retrieves the chain support for a chain (and whether it exists)
   139  func (ml *multiLedger) GetChain(chainID string) (ChainSupport, bool) {
   140  	cs, ok := ml.chains[chainID]
   141  	return cs, ok
   142  }
   143  
   144  func newConfigResources(configEnvelope *cb.ConfigEnvelope) (*configResources, error) {
   145  	initializer := configtx.NewInitializer()
   146  	configManager, err := configtx.NewManagerImpl(configEnvelope, initializer, nil)
   147  	if err != nil {
   148  		return nil, fmt.Errorf("Error unpacking config transaction: %s", err)
   149  	}
   150  
   151  	return &configResources{
   152  		Manager: configManager,
   153  	}, nil
   154  }
   155  
   156  func (ml *multiLedger) newLedgerResources(configTx *cb.Envelope) *ledgerResources {
   157  	payload := &cb.Payload{}
   158  	err := proto.Unmarshal(configTx.Payload, payload)
   159  	if err != nil {
   160  		logger.Fatalf("Error unmarshaling a config transaction payload: %s", err)
   161  	}
   162  
   163  	configEnvelope := &cb.ConfigEnvelope{}
   164  	err = proto.Unmarshal(payload.Data, configEnvelope)
   165  	if err != nil {
   166  		logger.Fatalf("Error unmarshaling a config transaction to config envelope: %s", err)
   167  	}
   168  
   169  	configResources, err := newConfigResources(configEnvelope)
   170  
   171  	if err != nil {
   172  		logger.Fatalf("Error creating configtx manager and handlers: %s", err)
   173  	}
   174  
   175  	chainID := configResources.ChainID()
   176  
   177  	ledger, err := ml.ledgerFactory.GetOrCreate(chainID)
   178  	if err != nil {
   179  		logger.Fatalf("Error getting ledger for %s", chainID)
   180  	}
   181  
   182  	return &ledgerResources{
   183  		configResources: configResources,
   184  		ledger:          ledger,
   185  	}
   186  }
   187  
   188  func (ml *multiLedger) newChain(configtx *cb.Envelope) {
   189  	ledgerResources := ml.newLedgerResources(configtx)
   190  	ledgerResources.ledger.Append(ordererledger.CreateNextBlock(ledgerResources.ledger, []*cb.Envelope{configtx}))
   191  
   192  	// Copy the map to allow concurrent reads from broadcast/deliver while the new chainSupport is
   193  	newChains := make(map[string]*chainSupport)
   194  	for key, value := range ml.chains {
   195  		newChains[key] = value
   196  	}
   197  
   198  	cs := newChainSupport(createStandardFilters(ledgerResources), ledgerResources, ml.consenters, ml.signer)
   199  	chainID := ledgerResources.ChainID()
   200  
   201  	logger.Infof("Created and starting new chain %s", chainID)
   202  
   203  	newChains[string(chainID)] = cs
   204  	cs.start()
   205  
   206  	ml.chains = newChains
   207  }