github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/peer/peer.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package peer
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"net"
    13  	"sync"
    14  
    15  	"github.com/hyperledger/fabric/common/config"
    16  	"github.com/hyperledger/fabric/common/configtx"
    17  	configtxapi "github.com/hyperledger/fabric/common/configtx/api"
    18  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    19  	"github.com/hyperledger/fabric/common/flogging"
    20  	mockconfigtx "github.com/hyperledger/fabric/common/mocks/configtx"
    21  	mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
    22  	"github.com/hyperledger/fabric/common/policies"
    23  	"github.com/hyperledger/fabric/core/comm"
    24  	"github.com/hyperledger/fabric/core/committer"
    25  	"github.com/hyperledger/fabric/core/committer/txvalidator"
    26  	"github.com/hyperledger/fabric/core/ledger"
    27  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    28  	"github.com/hyperledger/fabric/gossip/api"
    29  	"github.com/hyperledger/fabric/gossip/service"
    30  	"github.com/hyperledger/fabric/msp"
    31  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    32  	"github.com/hyperledger/fabric/protos/common"
    33  	pb "github.com/hyperledger/fabric/protos/peer"
    34  	"github.com/hyperledger/fabric/protos/utils"
    35  	"github.com/spf13/viper"
    36  	"google.golang.org/grpc"
    37  )
    38  
    39  var peerLogger = flogging.MustGetLogger("peer")
    40  
    41  var peerServer comm.GRPCServer
    42  
    43  // singleton instance to manage CAs for the peer across channel config changes
    44  var rootCASupport = comm.GetCASupport()
    45  
    46  type chainSupport struct {
    47  	configtxapi.Manager
    48  	config.Application
    49  	ledger ledger.PeerLedger
    50  }
    51  
    52  func (cs *chainSupport) Ledger() ledger.PeerLedger {
    53  	return cs.ledger
    54  }
    55  
    56  func (cs *chainSupport) GetMSPIDs(cid string) []string {
    57  	return GetMSPIDs(cid)
    58  }
    59  
    60  // chain is a local struct to manage objects in a chain
    61  type chain struct {
    62  	cs        *chainSupport
    63  	cb        *common.Block
    64  	committer committer.Committer
    65  }
    66  
    67  // chains is a local map of chainID->chainObject
    68  var chains = struct {
    69  	sync.RWMutex
    70  	list map[string]*chain
    71  }{list: make(map[string]*chain)}
    72  
    73  //MockInitialize resets chains for test env
    74  func MockInitialize() {
    75  	ledgermgmt.InitializeTestEnv()
    76  	chains.list = nil
    77  	chains.list = make(map[string]*chain)
    78  	chainInitializer = func(string) { return }
    79  }
    80  
    81  var chainInitializer func(string)
    82  
    83  var mockMSPIDGetter func(string) []string
    84  
    85  func MockSetMSPIDGetter(mspIDGetter func(string) []string) {
    86  	mockMSPIDGetter = mspIDGetter
    87  }
    88  
    89  // Initialize sets up any chains that the peer has from the persistence. This
    90  // function should be called at the start up when the ledger and gossip
    91  // ready
    92  func Initialize(init func(string)) {
    93  	chainInitializer = init
    94  
    95  	var cb *common.Block
    96  	var ledger ledger.PeerLedger
    97  	ledgermgmt.Initialize()
    98  	ledgerIds, err := ledgermgmt.GetLedgerIDs()
    99  	if err != nil {
   100  		panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err))
   101  	}
   102  	for _, cid := range ledgerIds {
   103  		peerLogger.Infof("Loading chain %s", cid)
   104  		if ledger, err = ledgermgmt.OpenLedger(cid); err != nil {
   105  			peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err)
   106  			peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
   107  			continue
   108  		}
   109  		if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil {
   110  			peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err)
   111  			peerLogger.Debugf("Error while looking for config block on ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
   112  			continue
   113  		}
   114  		// Create a chain if we get a valid ledger with config block
   115  		if err = createChain(cid, ledger, cb); err != nil {
   116  			peerLogger.Warningf("Failed to load chain %s(%s)", cid, err)
   117  			peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err)
   118  			continue
   119  		}
   120  
   121  		InitChain(cid)
   122  	}
   123  }
   124  
   125  // Take care to initialize chain after peer joined, for example deploys system CCs
   126  func InitChain(cid string) {
   127  	if chainInitializer != nil {
   128  		// Initialize chaincode, namely deploy system CC
   129  		peerLogger.Debugf("Init chain %s", cid)
   130  		chainInitializer(cid)
   131  	}
   132  }
   133  
   134  func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, error) {
   135  	peerLogger.Debugf("Getting config block")
   136  
   137  	// get last block.  Last block number is Height-1
   138  	blockchainInfo, err := ledger.GetBlockchainInfo()
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	lastBlock, err := ledger.GetBlockByNumber(blockchainInfo.Height - 1)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	// get most recent config block location from last block metadata
   148  	configBlockIndex, err := utils.GetLastConfigIndexFromBlock(lastBlock)
   149  	if err != nil {
   150  		return nil, err
   151  	}
   152  
   153  	// get most recent config block
   154  	configBlock, err := ledger.GetBlockByNumber(configBlockIndex)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  
   159  	peerLogger.Debugf("Got config block[%d]", configBlockIndex)
   160  	return configBlock, nil
   161  }
   162  
   163  // createChain creates a new chain object and insert it into the chains
   164  func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
   165  
   166  	envelopeConfig, err := utils.ExtractEnvelope(cb, 0)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	configtxInitializer := configtx.NewInitializer()
   172  
   173  	gossipEventer := service.GetGossipService().NewConfigEventer()
   174  
   175  	gossipCallbackWrapper := func(cm configtxapi.Manager) {
   176  		ac, ok := configtxInitializer.ApplicationConfig()
   177  		if !ok {
   178  			// TODO, handle a missing ApplicationConfig more gracefully
   179  			ac = nil
   180  		}
   181  		gossipEventer.ProcessConfigUpdate(&chainSupport{
   182  			Manager:     cm,
   183  			Application: ac,
   184  		})
   185  		service.GetGossipService().SuspectPeers(func(identity api.PeerIdentityType) bool {
   186  			// TODO: this is a place-holder that would somehow make the MSP layer suspect
   187  			// that a given certificate is revoked, or its intermediate CA is revoked.
   188  			// In the meantime, before we have such an ability, we return true in order
   189  			// to suspect ALL identities in order to validate all of them.
   190  			return true
   191  		})
   192  	}
   193  
   194  	trustedRootsCallbackWrapper := func(cm configtxapi.Manager) {
   195  		updateTrustedRoots(cm)
   196  	}
   197  
   198  	configtxManager, err := configtx.NewManagerImpl(
   199  		envelopeConfig,
   200  		configtxInitializer,
   201  		[]func(cm configtxapi.Manager){gossipCallbackWrapper, trustedRootsCallbackWrapper},
   202  	)
   203  	if err != nil {
   204  		return err
   205  	}
   206  
   207  	// TODO remove once all references to mspmgmt are gone from peer code
   208  	mspmgmt.XXXSetMSPManager(cid, configtxManager.MSPManager())
   209  
   210  	ac, ok := configtxInitializer.ApplicationConfig()
   211  	if !ok {
   212  		ac = nil
   213  	}
   214  	cs := &chainSupport{
   215  		Manager:     configtxManager,
   216  		Application: ac, // TODO, refactor as this is accessible through Manager
   217  		ledger:      ledger,
   218  	}
   219  
   220  	c := committer.NewLedgerCommitterReactive(ledger, txvalidator.NewTxValidator(cs), func(block *common.Block) error {
   221  		chainID, err := utils.GetChainIDFromBlock(block)
   222  		if err != nil {
   223  			return err
   224  		}
   225  		return SetCurrConfigBlock(block, chainID)
   226  	})
   227  
   228  	ordererAddresses := configtxManager.ChannelConfig().OrdererAddresses()
   229  	if len(ordererAddresses) == 0 {
   230  		return errors.New("No ordering service endpoint provided in configuration block")
   231  	}
   232  	service.GetGossipService().InitializeChannel(cs.ChainID(), c, ordererAddresses)
   233  
   234  	chains.Lock()
   235  	defer chains.Unlock()
   236  	chains.list[cid] = &chain{
   237  		cs:        cs,
   238  		cb:        cb,
   239  		committer: c,
   240  	}
   241  	return nil
   242  }
   243  
   244  // CreateChainFromBlock creates a new chain from config block
   245  func CreateChainFromBlock(cb *common.Block) error {
   246  	cid, err := utils.GetChainIDFromBlock(cb)
   247  	if err != nil {
   248  		return err
   249  	}
   250  
   251  	var l ledger.PeerLedger
   252  	if l, err = ledgermgmt.CreateLedger(cb); err != nil {
   253  		return fmt.Errorf("Cannot create ledger from genesis block, due to %s", err)
   254  	}
   255  
   256  	return createChain(cid, l, cb)
   257  }
   258  
   259  // MockCreateChain used for creating a ledger for a chain for tests
   260  // without havin to join
   261  func MockCreateChain(cid string) error {
   262  	var ledger ledger.PeerLedger
   263  	var err error
   264  
   265  	if ledger = GetLedger(cid); ledger == nil {
   266  		gb, _ := configtxtest.MakeGenesisBlock(cid)
   267  		if ledger, err = ledgermgmt.CreateLedger(gb); err != nil {
   268  			return err
   269  		}
   270  	}
   271  
   272  	// Here we need to mock also the policy manager
   273  	// in order for the ACL to be checked
   274  	initializer := mockconfigtx.Initializer{
   275  		Resources: mockconfigtx.Resources{
   276  			PolicyManagerVal: &mockpolicies.Manager{
   277  				Policy: &mockpolicies.Policy{},
   278  			},
   279  		},
   280  		PolicyProposerVal: &mockconfigtx.PolicyProposer{
   281  			Transactional: mockconfigtx.Transactional{},
   282  		},
   283  		ValueProposerVal: &mockconfigtx.ValueProposer{
   284  			Transactional: mockconfigtx.Transactional{},
   285  		},
   286  	}
   287  	manager := &mockconfigtx.Manager{
   288  		Initializer: initializer,
   289  	}
   290  
   291  	chains.Lock()
   292  	defer chains.Unlock()
   293  
   294  	chains.list[cid] = &chain{
   295  		cs: &chainSupport{
   296  			Manager: manager,
   297  			ledger:  ledger},
   298  	}
   299  
   300  	return nil
   301  }
   302  
   303  // GetLedger returns the ledger of the chain with chain ID. Note that this
   304  // call returns nil if chain cid has not been created.
   305  func GetLedger(cid string) ledger.PeerLedger {
   306  	chains.RLock()
   307  	defer chains.RUnlock()
   308  	if c, ok := chains.list[cid]; ok {
   309  		return c.cs.ledger
   310  	}
   311  	return nil
   312  }
   313  
   314  // GetPolicyManager returns the policy manager of the chain with chain ID. Note that this
   315  // call returns nil if chain cid has not been created.
   316  func GetPolicyManager(cid string) policies.Manager {
   317  	chains.RLock()
   318  	defer chains.RUnlock()
   319  	if c, ok := chains.list[cid]; ok {
   320  		return c.cs.PolicyManager()
   321  	}
   322  	return nil
   323  }
   324  
   325  // GetCurrConfigBlock returns the cached config block of the specified chain.
   326  // Note that this call returns nil if chain cid has not been created.
   327  func GetCurrConfigBlock(cid string) *common.Block {
   328  	chains.RLock()
   329  	defer chains.RUnlock()
   330  	if c, ok := chains.list[cid]; ok {
   331  		return c.cb
   332  	}
   333  	return nil
   334  }
   335  
   336  // updates the trusted roots for the peer based on updates to channels
   337  func updateTrustedRoots(cm configtxapi.Manager) {
   338  	// this is triggered on per channel basis so first update the roots for the channel
   339  	peerLogger.Debugf("Updating trusted root authorities for channel %s", cm.ChainID())
   340  	var secureConfig comm.SecureServerConfig
   341  	var err error
   342  	// only run is TLS is enabled
   343  	secureConfig, err = GetSecureConfig()
   344  	if err == nil && secureConfig.UseTLS {
   345  		buildTrustedRootsForChain(cm)
   346  
   347  		// now iterate over all roots for all app and orderer chains
   348  		trustedRoots := [][]byte{}
   349  		rootCASupport.RLock()
   350  		defer rootCASupport.RUnlock()
   351  		for _, roots := range rootCASupport.AppRootCAsByChain {
   352  			trustedRoots = append(trustedRoots, roots...)
   353  		}
   354  		// also need to append statically configured root certs
   355  		if len(secureConfig.ClientRootCAs) > 0 {
   356  			trustedRoots = append(trustedRoots, secureConfig.ClientRootCAs...)
   357  		}
   358  		if len(secureConfig.ServerRootCAs) > 0 {
   359  			trustedRoots = append(trustedRoots, secureConfig.ServerRootCAs...)
   360  		}
   361  
   362  		server := GetPeerServer()
   363  		// now update the client roots for the peerServer
   364  		if server != nil {
   365  			err := server.SetClientRootCAs(trustedRoots)
   366  			if err != nil {
   367  				msg := "Failed to update trusted roots for peer from latest config " +
   368  					"block.  This peer may not be able to communicate " +
   369  					"with members of channel %s (%s)"
   370  				peerLogger.Warningf(msg, cm.ChainID(), err)
   371  			}
   372  		}
   373  	}
   374  }
   375  
   376  // populates the appRootCAs and orderRootCAs maps by getting the
   377  // root and intermediate certs for all msps associated with the MSPManager
   378  func buildTrustedRootsForChain(cm configtxapi.Manager) {
   379  	rootCASupport.Lock()
   380  	defer rootCASupport.Unlock()
   381  
   382  	appRootCAs := [][]byte{}
   383  	ordererRootCAs := [][]byte{}
   384  	appOrgMSPs := make(map[string]struct{})
   385  	ordOrgMSPs := make(map[string]struct{})
   386  
   387  	if ac, ok := cm.ApplicationConfig(); ok {
   388  		//loop through app orgs and build map of MSPIDs
   389  		for _, appOrg := range ac.Organizations() {
   390  			appOrgMSPs[appOrg.MSPID()] = struct{}{}
   391  		}
   392  	}
   393  
   394  	if ac, ok := cm.OrdererConfig(); ok {
   395  		//loop through orderer orgs and build map of MSPIDs
   396  		for _, ordOrg := range ac.Organizations() {
   397  			ordOrgMSPs[ordOrg.MSPID()] = struct{}{}
   398  		}
   399  	}
   400  
   401  	cid := cm.ChainID()
   402  	peerLogger.Debugf("updating root CAs for channel [%s]", cid)
   403  	msps, err := cm.MSPManager().GetMSPs()
   404  	if err != nil {
   405  		peerLogger.Errorf("Error getting root CAs for channel %s (%s)", cid, err)
   406  	}
   407  	if err == nil {
   408  		for k, v := range msps {
   409  			// check to see if this is a FABRIC MSP
   410  			if v.GetType() == msp.FABRIC {
   411  				for _, root := range v.GetTLSRootCerts() {
   412  					// check to see of this is an app org MSP
   413  					if _, ok := appOrgMSPs[k]; ok {
   414  						peerLogger.Debugf("adding app root CAs for MSP [%s]", k)
   415  						appRootCAs = append(appRootCAs, root)
   416  					}
   417  					// check to see of this is an orderer org MSP
   418  					if _, ok := ordOrgMSPs[k]; ok {
   419  						peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k)
   420  						ordererRootCAs = append(ordererRootCAs, root)
   421  					}
   422  				}
   423  				for _, intermediate := range v.GetTLSIntermediateCerts() {
   424  					// check to see of this is an app org MSP
   425  					if _, ok := appOrgMSPs[k]; ok {
   426  						peerLogger.Debugf("adding app root CAs for MSP [%s]", k)
   427  						appRootCAs = append(appRootCAs, intermediate)
   428  					}
   429  					// check to see of this is an orderer org MSP
   430  					if _, ok := ordOrgMSPs[k]; ok {
   431  						peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k)
   432  						ordererRootCAs = append(ordererRootCAs, intermediate)
   433  					}
   434  				}
   435  			}
   436  		}
   437  		rootCASupport.AppRootCAsByChain[cid] = appRootCAs
   438  		rootCASupport.OrdererRootCAsByChain[cid] = ordererRootCAs
   439  	}
   440  }
   441  
   442  // GetMSPIDs returns the ID of each application MSP defined on this chain
   443  func GetMSPIDs(cid string) []string {
   444  	chains.RLock()
   445  	defer chains.RUnlock()
   446  
   447  	//if mock is set, use it to return MSPIDs
   448  	//used for tests without a proper join
   449  	if mockMSPIDGetter != nil {
   450  		return mockMSPIDGetter(cid)
   451  	}
   452  	if c, ok := chains.list[cid]; ok {
   453  		if c == nil || c.cs == nil {
   454  			return nil
   455  		}
   456  		ac, ok := c.cs.ApplicationConfig()
   457  		if !ok || ac.Organizations() == nil {
   458  			return nil
   459  		}
   460  
   461  		orgs := ac.Organizations()
   462  		toret := make([]string, len(orgs))
   463  		i := 0
   464  		for _, org := range orgs {
   465  			toret[i] = org.MSPID()
   466  			i++
   467  		}
   468  
   469  		return toret
   470  	}
   471  	return nil
   472  }
   473  
   474  // SetCurrConfigBlock sets the current config block of the specified chain
   475  func SetCurrConfigBlock(block *common.Block, cid string) error {
   476  	chains.Lock()
   477  	defer chains.Unlock()
   478  	if c, ok := chains.list[cid]; ok {
   479  		c.cb = block
   480  		return nil
   481  	}
   482  	return fmt.Errorf("Chain %s doesn't exist on the peer", cid)
   483  }
   484  
   485  // NewPeerClientConnection Returns a new grpc.ClientConn to the configured local PEER.
   486  func NewPeerClientConnection() (*grpc.ClientConn, error) {
   487  	return NewPeerClientConnectionWithAddress(viper.GetString("peer.address"))
   488  }
   489  
   490  // GetLocalIP returns the non loopback local IP of the host
   491  func GetLocalIP() string {
   492  	addrs, err := net.InterfaceAddrs()
   493  	if err != nil {
   494  		return ""
   495  	}
   496  	for _, address := range addrs {
   497  		// check the address type and if it is not a loopback then display it
   498  		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
   499  			if ipnet.IP.To4() != nil {
   500  				return ipnet.IP.String()
   501  			}
   502  		}
   503  	}
   504  	return ""
   505  }
   506  
   507  // NewPeerClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER.
   508  func NewPeerClientConnectionWithAddress(peerAddress string) (*grpc.ClientConn, error) {
   509  	if comm.TLSEnabled() {
   510  		return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
   511  	}
   512  	return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
   513  }
   514  
   515  // GetChannelsInfo returns an array with information about all channels for
   516  // this peer
   517  func GetChannelsInfo() []*pb.ChannelInfo {
   518  	// array to store metadata for all channels
   519  	var channelInfoArray []*pb.ChannelInfo
   520  
   521  	chains.RLock()
   522  	defer chains.RUnlock()
   523  	for key := range chains.list {
   524  		channelInfo := &pb.ChannelInfo{ChannelId: key}
   525  
   526  		// add this specific chaincode's metadata to the array of all chaincodes
   527  		channelInfoArray = append(channelInfoArray, channelInfo)
   528  	}
   529  
   530  	return channelInfoArray
   531  }
   532  
   533  // NewChannelPolicyManagerGetter returns a new instance of ChannelPolicyManagerGetter
   534  func NewChannelPolicyManagerGetter() policies.ChannelPolicyManagerGetter {
   535  	return &channelPolicyManagerGetter{}
   536  }
   537  
   538  type channelPolicyManagerGetter struct{}
   539  
   540  func (c *channelPolicyManagerGetter) Manager(channelID string) (policies.Manager, bool) {
   541  	policyManager := GetPolicyManager(channelID)
   542  	return policyManager, policyManager != nil
   543  }
   544  
   545  // CreatePeerServer creates an instance of comm.GRPCServer
   546  // This server is used for peer communications
   547  func CreatePeerServer(listenAddress string,
   548  	secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
   549  
   550  	var err error
   551  	peerServer, err = comm.NewGRPCServer(listenAddress, secureConfig)
   552  	if err != nil {
   553  		peerLogger.Errorf("Failed to create peer server (%s)", err)
   554  		return nil, err
   555  	}
   556  	return peerServer, nil
   557  }
   558  
   559  // GetPeerServer returns the peer server instance
   560  func GetPeerServer() comm.GRPCServer {
   561  	return peerServer
   562  }